* [PATCH v2 0/3] Tegra AC97 v2
@ 2013-01-05 1:18 Lucas Stach
[not found] ` <1357348725-32139-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
0 siblings, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2013-01-05 1:18 UTC (permalink / raw)
To: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, Stephen Warren,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
v2 of the Tegra AC97 series. Unmerged ASoC related patches only.
The machine driver now instantiates the codec driver by itself,
without usage of DT. Other fixups for review feedback also included.
I'll post a patch for the AC97 clock once Prashant patches land
in a branch.
Lucas Stach (3):
ASoC: tegra: add ac97 host driver
ASoC: tegra: add ac97 host controller to device tree
ASoC: tegra: add tegra machine driver using wm9712 codec
.../bindings/sound/nvidia,tegra-audio-wm9712.txt | 51 +++
.../bindings/sound/nvidia,tegra20-ac97.txt | 22 +
arch/arm/boot/dts/tegra20.dtsi | 9 +
sound/soc/tegra/Kconfig | 19 +
sound/soc/tegra/Makefile | 4 +
sound/soc/tegra/tegra20_ac97.c | 480 +++++++++++++++++++++
sound/soc/tegra/tegra20_ac97.h | 95 ++++
sound/soc/tegra/tegra_wm9712.c | 179 ++++++++
8 files changed, 859 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt
create mode 100644 sound/soc/tegra/tegra20_ac97.c
create mode 100644 sound/soc/tegra/tegra20_ac97.h
create mode 100644 sound/soc/tegra/tegra_wm9712.c
--
1.8.0.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 1/3] ASoC: tegra: add ac97 host driver
[not found] ` <1357348725-32139-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
@ 2013-01-05 1:18 ` Lucas Stach
[not found] ` <1357348725-32139-2-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-05 1:18 ` [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree Lucas Stach
2013-01-05 1:18 ` [PATCH v2 3/3] ASoC: tegra: add tegra machine driver using wm9712 codec Lucas Stach
2 siblings, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2013-01-05 1:18 UTC (permalink / raw)
To: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, Stephen Warren,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
This adds the driver for the Tegra 2x AC97 host controller.
Signed-off-by: Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
---
v2:
- squash DT binding file into this patch
- various small fixups all over
---
.../bindings/sound/nvidia,tegra20-ac97.txt | 22 +
sound/soc/tegra/Kconfig | 10 +
sound/soc/tegra/Makefile | 2 +
sound/soc/tegra/tegra20_ac97.c | 480 +++++++++++++++++++++
sound/soc/tegra/tegra20_ac97.h | 95 ++++
5 files changed, 609 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt
create mode 100644 sound/soc/tegra/tegra20_ac97.c
create mode 100644 sound/soc/tegra/tegra20_ac97.h
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt
new file mode 100644
index 0000000..c145497
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt
@@ -0,0 +1,22 @@
+NVIDIA Tegra 20 AC97 controller
+
+Required properties:
+- compatible : "nvidia,tegra20-ac97"
+- reg : Should contain AC97 controller registers location and length
+- interrupts : Should contain AC97 interrupt
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+ request selector for the AC97 controller
+- nvidia,codec-reset-gpio : The Tegra GPIO controller's phandle and the number
+ of the GPIO used to reset the external AC97 codec
+- nvidia,codec-sync-gpio : The Tegra GPIO controller's phandle and the number
+ of the GPIO corresponding with the AC97 DAP _FS line
+Example:
+
+ac97@70002000 {
+ compatible = "nvidia,tegra20-ac97";
+ reg = <0x70002000 0x200>;
+ interrupts = <0 81 0x04>;
+ nvidia,dma-request-selector = <&apbdma 12>;
+ nvidia,codec-reset-gpio = <&gpio 170 0>;
+ nvidia,codec-sync-gpio = <&gpio 120 0>;
+};
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 19e5fe7..4b3a2b8 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -6,6 +6,16 @@ config SND_SOC_TEGRA
help
Say Y or M here if you want support for SoC audio on Tegra.
+config SND_SOC_TEGRA20_AC97
+ tristate
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+ select SND_SOC_AC97_BUS
+ select SND_SOC_TEGRA20_DAS
+ help
+ Say Y or M if you want to add support for codecs attached to the
+ Tegra20 AC97 interface. You will also need to select the individual
+ machine drivers to support below.
+
config SND_SOC_TEGRA20_DAS
tristate
depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 391e78a..02513d9 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -1,6 +1,7 @@
# Tegra platform Support
snd-soc-tegra-pcm-objs := tegra_pcm.o
snd-soc-tegra-utils-objs += tegra_asoc_utils.o
+snd-soc-tegra20-ac97-objs := tegra20_ac97.o
snd-soc-tegra20-das-objs := tegra20_das.o
snd-soc-tegra20-i2s-objs := tegra20_i2s.o
snd-soc-tegra20-spdif-objs := tegra20_spdif.o
@@ -9,6 +10,7 @@ snd-soc-tegra30-i2s-objs := tegra30_i2s.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
+obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
obj-$(CONFIG_SND_SOC_TEGRA20_DAS) += snd-soc-tegra20-das.o
obj-$(CONFIG_SND_SOC_TEGRA20_I2S) += snd-soc-tegra20-i2s.o
obj-$(CONFIG_SND_SOC_TEGRA20_SPDIF) += snd-soc-tegra20-spdif.o
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
new file mode 100644
index 0000000..1bae73b
--- /dev/null
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -0,0 +1,480 @@
+/*
+ * tegra20_ac97.c - Tegra20 AC97 platform driver
+ *
+ * Copyright (c) 2012 Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
+ *
+ * Partly based on code copyright/by:
+ *
+ * Copyright (c) 2011,2012 Toradex Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra_asoc_utils.h"
+#include "tegra20_ac97.h"
+
+#define DRV_NAME "tegra20-ac97"
+
+static struct tegra20_ac97 *workdata;
+
+static void tegra20_ac97_codec_reset(struct snd_ac97 *ac97)
+{
+ u32 readback;
+ unsigned long timeout;
+
+ /* reset line is not driven by DAC pad group, have to toggle GPIO */
+ gpio_set_value(workdata->reset_gpio, 0);
+ udelay(2);
+
+ gpio_set_value(workdata->reset_gpio, 1);
+ udelay(2);
+
+ timeout = jiffies + msecs_to_jiffies(100);
+
+ do {
+ regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback);
+ if (readback & TEGRA20_AC97_STATUS1_CODEC1_RDY)
+ break;
+ usleep_range(1000, 2000);
+ } while (!time_after(jiffies, timeout));
+}
+
+static void tegra20_ac97_codec_warm_reset(struct snd_ac97 *ac97)
+{
+ u32 readback;
+ unsigned long timeout;
+
+ /*
+ * although sync line is driven by the DAC pad group warm reset using
+ * the controller cmd is not working, have to toggle sync line
+ * manually.
+ */
+ gpio_request(workdata->sync_gpio, "codec-sync");
+
+ gpio_direction_output(workdata->sync_gpio, 1);
+
+ udelay(2);
+ gpio_set_value(workdata->sync_gpio, 0);
+ udelay(2);
+ gpio_free(workdata->sync_gpio);
+
+ timeout = jiffies + msecs_to_jiffies(100);
+
+ do {
+ regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback);
+ if (readback & TEGRA20_AC97_STATUS1_CODEC1_RDY)
+ break;
+ usleep_range(1000, 2000);
+ } while (!time_after(jiffies, timeout));
+}
+
+static unsigned short tegra20_ac97_codec_read(struct snd_ac97 *ac97_snd,
+ unsigned short reg)
+{
+ u32 readback;
+ unsigned long timeout;
+
+ regmap_write(workdata->regmap, TEGRA20_AC97_CMD,
+ (((reg | 0x80) << TEGRA20_AC97_CMD_CMD_ADDR_SHIFT) &
+ TEGRA20_AC97_CMD_CMD_ADDR_MASK) |
+ TEGRA20_AC97_CMD_BUSY);
+
+ timeout = jiffies + msecs_to_jiffies(100);
+
+ do {
+ regmap_read(workdata->regmap, TEGRA20_AC97_STATUS1, &readback);
+ if (readback & TEGRA20_AC97_STATUS1_STA_VALID1)
+ break;
+ usleep_range(1000, 2000);
+ } while (!time_after(jiffies, timeout));
+
+ return ((readback & TEGRA20_AC97_STATUS1_STA_DATA1_MASK) >>
+ TEGRA20_AC97_STATUS1_STA_DATA1_SHIFT);
+}
+
+static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd,
+ unsigned short reg, unsigned short val)
+{
+ u32 readback;
+ unsigned long timeout;
+
+ regmap_write(workdata->regmap, TEGRA20_AC97_CMD,
+ ((reg << TEGRA20_AC97_CMD_CMD_ADDR_SHIFT) &
+ TEGRA20_AC97_CMD_CMD_ADDR_MASK) |
+ ((val << TEGRA20_AC97_CMD_CMD_DATA_SHIFT) &
+ TEGRA20_AC97_CMD_CMD_DATA_MASK) |
+ TEGRA20_AC97_CMD_BUSY);
+
+ timeout = jiffies + msecs_to_jiffies(100);
+
+ do {
+ regmap_read(workdata->regmap, TEGRA20_AC97_CMD, &readback);
+ if (!(readback & TEGRA20_AC97_CMD_BUSY))
+ break;
+ usleep_range(1000, 2000);
+ } while (!time_after(jiffies, timeout));
+}
+
+struct snd_ac97_bus_ops soc_ac97_ops = {
+ .read = tegra20_ac97_codec_read,
+ .write = tegra20_ac97_codec_write,
+ .reset = tegra20_ac97_codec_reset,
+ .warm_reset = tegra20_ac97_codec_warm_reset,
+};
+EXPORT_SYMBOL_GPL(soc_ac97_ops);
+
+static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97)
+{
+ regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
+ TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN,
+ TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN);
+
+ regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
+ TEGRA20_AC97_CTRL_PCM_DAC_EN |
+ TEGRA20_AC97_CTRL_STM_EN,
+ TEGRA20_AC97_CTRL_PCM_DAC_EN |
+ TEGRA20_AC97_CTRL_STM_EN);
+}
+
+static inline void tegra20_ac97_stop_playback(struct tegra20_ac97 *ac97)
+{
+ regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
+ TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 0);
+
+ regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
+ TEGRA20_AC97_CTRL_PCM_DAC_EN, 0);
+}
+
+static inline void tegra20_ac97_start_capture(struct tegra20_ac97 *ac97)
+{
+ regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
+ TEGRA20_AC97_FIFO_SCR_REC_FULL_EN,
+ TEGRA20_AC97_FIFO_SCR_REC_FULL_EN);
+}
+
+static inline void tegra20_ac97_stop_capture(struct tegra20_ac97 *ac97)
+{
+ regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
+ TEGRA20_AC97_FIFO_SCR_REC_FULL_EN, 0);
+}
+
+static int tegra20_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra20_ac97_start_playback(ac97);
+ else
+ tegra20_ac97_start_capture(ac97);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra20_ac97_stop_playback(ac97);
+ else
+ tegra20_ac97_stop_capture(ac97);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops tegra20_ac97_dai_ops = {
+ .trigger = tegra20_ac97_trigger,
+};
+
+static int tegra20_ac97_probe(struct snd_soc_dai *dai)
+{
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai);
+
+ dai->capture_dma_data = &ac97->capture_dma_data;
+ dai->playback_dma_data = &ac97->playback_dma_data;
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver tegra20_ac97_dai = {
+ .name = "tegra-ac97-pcm",
+ .ac97_control = 1,
+ .probe = tegra20_ac97_probe,
+ .playback = {
+ .stream_name = "PCM Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "PCM Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &tegra20_ac97_dai_ops,
+};
+
+static bool tegra20_ac97_wr_rd_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_AC97_CTRL:
+ case TEGRA20_AC97_CMD:
+ case TEGRA20_AC97_STATUS1:
+ case TEGRA20_AC97_FIFO1_SCR:
+ case TEGRA20_AC97_FIFO_TX1:
+ case TEGRA20_AC97_FIFO_RX1:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static bool tegra20_ac97_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_AC97_STATUS1:
+ case TEGRA20_AC97_FIFO1_SCR:
+ case TEGRA20_AC97_FIFO_TX1:
+ case TEGRA20_AC97_FIFO_RX1:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static bool tegra20_ac97_precious_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA20_AC97_FIFO_TX1:
+ case TEGRA20_AC97_FIFO_RX1:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static const struct regmap_config tegra20_ac97_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA20_AC97_FIFO_RX1,
+ .writeable_reg = tegra20_ac97_wr_rd_reg,
+ .readable_reg = tegra20_ac97_wr_rd_reg,
+ .volatile_reg = tegra20_ac97_volatile_reg,
+ .precious_reg = tegra20_ac97_precious_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int tegra20_ac97_platform_probe(struct platform_device *pdev)
+{
+ struct tegra20_ac97 *ac97;
+ struct resource *mem, *memregion;
+ u32 of_dma[2];
+ void __iomem *regs;
+ int ret = 0;
+
+ ac97 = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_ac97),
+ GFP_KERNEL);
+ if (!ac97) {
+ dev_err(&pdev->dev, "Can't allocate tegra20_ac97\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ dev_set_drvdata(&pdev->dev, ac97);
+
+ ac97->clk_ac97 = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ac97->clk_ac97)) {
+ dev_err(&pdev->dev, "Can't retrieve ac97 clock\n");
+ ret = PTR_ERR(ac97->clk_ac97);
+ goto err;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "No memory resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+
+ memregion = devm_request_mem_region(&pdev->dev, mem->start,
+ resource_size(mem), DRV_NAME);
+ if (!memregion) {
+ dev_err(&pdev->dev, "Memory region already claimed\n");
+ ret = -EBUSY;
+ goto err_clk_put;
+ }
+
+ regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ if (!regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_clk_put;
+ }
+
+ ac97->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
+ &tegra20_ac97_regmap_config);
+ if (IS_ERR(ac97->regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ ret = PTR_ERR(ac97->regmap);
+ goto err_clk_put;
+ }
+
+ if (of_property_read_u32_array(pdev->dev.of_node,
+ "nvidia,dma-request-selector",
+ of_dma, 2) < 0) {
+ dev_err(&pdev->dev, "No DMA resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+
+ ac97->reset_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "nvidia,codec-reset-gpio", 0);
+ if (gpio_is_valid(ac97->reset_gpio)) {
+ ret = devm_gpio_request_one(&pdev->dev, ac97->reset_gpio,
+ GPIOF_OUT_INIT_HIGH, "codec-reset");
+ if (ret) {
+ dev_err(&pdev->dev, "could not get codec-reset GPIO\n");
+ goto err_clk_put;
+ }
+ } else {
+ dev_err(&pdev->dev, "no codec-reset GPIO supplied\n");
+ goto err_clk_put;
+ }
+
+ ac97->sync_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "nvidia,codec-sync-gpio", 0);
+ if (!gpio_is_valid(ac97->sync_gpio)) {
+ dev_err(&pdev->dev, "no codec-sync GPIO supplied\n");
+ goto err_clk_put;
+ }
+
+ ac97->capture_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_RX1;
+ ac97->capture_dma_data.wrap = 4;
+ ac97->capture_dma_data.width = 32;
+ ac97->capture_dma_data.req_sel = of_dma[1];
+
+ ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1;
+ ac97->playback_dma_data.wrap = 4;
+ ac97->playback_dma_data.width = 32;
+ ac97->playback_dma_data.req_sel = of_dma[1];
+
+ ret = snd_soc_register_dais(&pdev->dev, &tegra20_ac97_dai, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
+ ret = -ENOMEM;
+ goto err_clk_put;
+ }
+
+ ret = tegra_pcm_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
+ goto err_unregister_dai;
+ }
+
+ ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev);
+ if (ret)
+ goto err_unregister_pcm;
+
+ ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data);
+ if (ret)
+ goto err_asoc_utils_fini;
+
+ ret = clk_prepare_enable(ac97->clk_ac97);
+ if (ret) {
+ dev_err(&pdev->dev, "clk_enable failed: %d\n", ret);
+ goto err_asoc_utils_fini;
+ }
+
+ /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */
+ workdata = ac97;
+
+ return 0;
+
+err_asoc_utils_fini:
+ tegra_asoc_utils_fini(&ac97->util_data);
+err_unregister_pcm:
+ tegra_pcm_platform_unregister(&pdev->dev);
+err_unregister_dai:
+ snd_soc_unregister_dai(&pdev->dev);
+err_clk_put:
+ clk_put(ac97->clk_ac97);
+err:
+ return ret;
+}
+
+static int tegra20_ac97_platform_remove(struct platform_device *pdev)
+{
+ struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev);
+
+ tegra_pcm_platform_unregister(&pdev->dev);
+ snd_soc_unregister_dai(&pdev->dev);
+
+ tegra_asoc_utils_fini(&ac97->util_data);
+
+ clk_disable_unprepare(ac97->clk_ac97);
+ clk_put(ac97->clk_ac97);
+
+ return 0;
+}
+
+static const struct of_device_id tegra20_ac97_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-ac97", },
+ {},
+};
+
+static struct platform_driver tegra20_ac97_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra20_ac97_of_match,
+ },
+ .probe = tegra20_ac97_platform_probe,
+ .remove = tegra20_ac97_platform_remove,
+};
+module_platform_driver(tegra20_ac97_driver);
+
+MODULE_AUTHOR("Lucas Stach");
+MODULE_DESCRIPTION("Tegra20 AC97 ASoC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match);
diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h
new file mode 100644
index 0000000..dddc682
--- /dev/null
+++ b/sound/soc/tegra/tegra20_ac97.h
@@ -0,0 +1,95 @@
+/*
+ * tegra20_ac97.h - Definitions for the Tegra20 AC97 controller driver
+ *
+ * Copyright (c) 2012 Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
+ *
+ * Partly based on code copyright/by:
+ *
+ * Copyright (c) 2011,2012 Toradex Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __TEGRA20_AC97_H__
+#define __TEGRA20_AC97_H__
+
+#include "tegra_pcm.h"
+
+#define TEGRA20_AC97_CTRL 0x00
+#define TEGRA20_AC97_CMD 0x04
+#define TEGRA20_AC97_STATUS1 0x08
+/* ... */
+#define TEGRA20_AC97_FIFO1_SCR 0x1c
+/* ... */
+#define TEGRA20_AC97_FIFO_TX1 0x40
+#define TEGRA20_AC97_FIFO_RX1 0x80
+
+/* TEGRA20_AC97_CTRL */
+#define TEGRA20_AC97_CTRL_STM2_EN (1 << 16)
+#define TEGRA20_AC97_CTRL_DOUBLE_SAMPLING_EN (1 << 11)
+#define TEGRA20_AC97_CTRL_IO_CNTRL_EN (1 << 10)
+#define TEGRA20_AC97_CTRL_HSET_DAC_EN (1 << 9)
+#define TEGRA20_AC97_CTRL_LINE2_DAC_EN (1 << 8)
+#define TEGRA20_AC97_CTRL_PCM_LFE_EN (1 << 7)
+#define TEGRA20_AC97_CTRL_PCM_SUR_EN (1 << 6)
+#define TEGRA20_AC97_CTRL_PCM_CEN_DAC_EN (1 << 5)
+#define TEGRA20_AC97_CTRL_LINE1_DAC_EN (1 << 4)
+#define TEGRA20_AC97_CTRL_PCM_DAC_EN (1 << 3)
+#define TEGRA20_AC97_CTRL_COLD_RESET (1 << 2)
+#define TEGRA20_AC97_CTRL_WARM_RESET (1 << 1)
+#define TEGRA20_AC97_CTRL_STM_EN (1 << 0)
+
+/* TEGRA20_AC97_CMD */
+#define TEGRA20_AC97_CMD_CMD_ADDR_SHIFT 24
+#define TEGRA20_AC97_CMD_CMD_ADDR_MASK (0xff << TEGRA20_AC97_CMD_CMD_ADDR_SHIFT)
+#define TEGRA20_AC97_CMD_CMD_DATA_SHIFT 8
+#define TEGRA20_AC97_CMD_CMD_DATA_MASK (0xffff << TEGRA20_AC97_CMD_CMD_DATA_SHIFT)
+#define TEGRA20_AC97_CMD_CMD_ID_SHIFT 2
+#define TEGRA20_AC97_CMD_CMD_ID_MASK (0x3 << TEGRA20_AC97_CMD_CMD_ID_SHIFT)
+#define TEGRA20_AC97_CMD_BUSY (1 << 0)
+
+/* TEGRA20_AC97_STATUS1 */
+#define TEGRA20_AC97_STATUS1_STA_ADDR1_SHIFT 24
+#define TEGRA20_AC97_STATUS1_STA_ADDR1_MASK (0xff << TEGRA20_AC97_STATUS1_STA_ADDR1_SHIFT)
+#define TEGRA20_AC97_STATUS1_STA_DATA1_SHIFT 8
+#define TEGRA20_AC97_STATUS1_STA_DATA1_MASK (0xffff << TEGRA20_AC97_STATUS1_STA_DATA1_SHIFT)
+#define TEGRA20_AC97_STATUS1_STA_VALID1 (1 << 2)
+#define TEGRA20_AC97_STATUS1_STANDBY1 (1 << 1)
+#define TEGRA20_AC97_STATUS1_CODEC1_RDY (1 << 0)
+
+/* TEGRA20_AC97_FIFO1_SCR */
+#define TEGRA20_AC97_FIFO_SCR_REC_MT_CNT_SHIFT 27
+#define TEGRA20_AC97_FIFO_SCR_REC_MT_CNT_MASK (0x1f << TEGRA20_AC97_FIFO_SCR_REC_MT_CNT_SHIFT)
+#define TEGRA20_AC97_FIFO_SCR_PB_MT_CNT_SHIFT 22
+#define TEGRA20_AC97_FIFO_SCR_PB_MT_CNT_MASK (0x1f << TEGRA20_AC97_FIFO_SCR_PB_MT_CNT_SHIFT)
+#define TEGRA20_AC97_FIFO_SCR_REC_OVERRUN_INT_STA (1 << 19)
+#define TEGRA20_AC97_FIFO_SCR_PB_UNDERRUN_INT_STA (1 << 18)
+#define TEGRA20_AC97_FIFO_SCR_REC_FORCE_MT (1 << 17)
+#define TEGRA20_AC97_FIFO_SCR_PB_FORCE_MT (1 << 16)
+#define TEGRA20_AC97_FIFO_SCR_REC_FULL_EN (1 << 15)
+#define TEGRA20_AC97_FIFO_SCR_REC_3QRT_FULL_EN (1 << 14)
+#define TEGRA20_AC97_FIFO_SCR_REC_QRT_FULL_EN (1 << 13)
+#define TEGRA20_AC97_FIFO_SCR_REC_EMPTY_EN (1 << 12)
+#define TEGRA20_AC97_FIFO_SCR_PB_NOT_FULL_EN (1 << 11)
+#define TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN (1 << 10)
+#define TEGRA20_AC97_FIFO_SCR_PB_3QRT_MT_EN (1 << 9)
+#define TEGRA20_AC97_FIFO_SCR_PB_EMPTY_MT_EN (1 << 8)
+
+struct tegra20_ac97 {
+ struct clk *clk_ac97;
+ struct tegra_pcm_dma_params capture_dma_data;
+ struct tegra_pcm_dma_params playback_dma_data;
+ struct regmap *regmap;
+ int reset_gpio;
+ int sync_gpio;
+ struct tegra_asoc_utils_data util_data;
+};
+#endif /* __TEGRA20_AC97_H__ */
--
1.8.0.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree
[not found] ` <1357348725-32139-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-05 1:18 ` [PATCH v2 1/3] ASoC: tegra: add ac97 host driver Lucas Stach
@ 2013-01-05 1:18 ` Lucas Stach
[not found] ` <1357348725-32139-3-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-05 1:18 ` [PATCH v2 3/3] ASoC: tegra: add tegra machine driver using wm9712 codec Lucas Stach
2 siblings, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2013-01-05 1:18 UTC (permalink / raw)
To: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, Stephen Warren,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
Add default entry for the AC97 host controller.
Signed-off-by: Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
---
v2:
- only add .dtsi parts here
---
arch/arm/boot/dts/tegra20.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index b8effa1..1dc0423 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -177,6 +177,15 @@
compatible = "nvidia,tegra20-das";
reg = <0x70000c00 0x80>;
};
+
+ tegra_ac97: ac97 {
+ compatible = "nvidia,tegra20-ac97";
+ reg = <0x70002000 0x200>;
+ interrupts = <0 81 0x04>;
+ nvidia,dma-request-selector = <&apbdma 12>;
+ clocks = <&tegra_car 3>;
+ status = "disabled";
+ };
tegra_i2s1: i2s@70002800 {
compatible = "nvidia,tegra20-i2s";
--
1.8.0.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 3/3] ASoC: tegra: add tegra machine driver using wm9712 codec
[not found] ` <1357348725-32139-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-05 1:18 ` [PATCH v2 1/3] ASoC: tegra: add ac97 host driver Lucas Stach
2013-01-05 1:18 ` [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree Lucas Stach
@ 2013-01-05 1:18 ` Lucas Stach
[not found] ` <1357348725-32139-4-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2 siblings, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2013-01-05 1:18 UTC (permalink / raw)
To: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, Stephen Warren,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
This adds a very simple machine driver using the Wolfson wm9712 AC97
codec.
Signed-off-by: Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
---
v2:
- manually probe codec driver without using DT
- fixup Kconfig for select and depends
---
.../bindings/sound/nvidia,tegra-audio-wm9712.txt | 51 ++++++
sound/soc/tegra/Kconfig | 9 ++
sound/soc/tegra/Makefile | 2 +
sound/soc/tegra/tegra_wm9712.c | 179 +++++++++++++++++++++
4 files changed, 241 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
create mode 100644 sound/soc/tegra/tegra_wm9712.c
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
new file mode 100644
index 0000000..be35d34
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
@@ -0,0 +1,51 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-wm9712"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source. Valid names for sources and
+ sinks are the WM9712's pins, and the jacks on the board:
+
+ WM9712 pins:
+
+ * MONOOUT
+ * HPOUTL
+ * HPOUTR
+ * LOUT2
+ * ROUT2
+ * OUT3
+ * LINEINL
+ * LINEINR
+ * PHONE
+ * PCBEEP
+ * MIC1
+ * MIC2
+ * Mic Bias
+
+ Board connectors:
+
+ * Headphone
+ * LineIn
+ * Mic
+
+- nvidia,ac97-controller : The phandle of the Tegra AC97 controller
+
+
+Example:
+
+sound {
+ compatible = "nvidia,tegra-audio-wm9712-colibri_t20",
+ "nvidia,tegra-audio-wm9712";
+ nvidia,model = "Toradex Colibri T20";
+
+ nvidia,audio-routing =
+ "Headphone", "HPOUTL",
+ "Headphone", "HPOUTR",
+ "LineIn", "LINEINL",
+ "LineIn", "LINEINR",
+ "Mic", "MIC1";
+
+ nvidia,ac97-controller = <&ac97>;
+};
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 4b3a2b8..dbc27ce 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -80,6 +80,15 @@ config SND_SOC_TEGRA_WM8903
boards using the WM8093 codec. Currently, the supported boards are
Harmony, Ventana, Seaboard, Kaen, and Aebl.
+config SND_SOC_TEGRA_WM9712
+ tristate "SoC Audio support for Tegra boards using a WM9712 codec"
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA20_AC97
+ select SND_SOC_WM9712
+ help
+ Say Y or M here if you want to add support for SoC audio on Tegra
+ boards using the WM9712 (or compatible) codec.
+
config SND_SOC_TEGRA_TRIMSLICE
tristate "SoC Audio support for TrimSlice board"
depends on SND_SOC_TEGRA && I2C
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 02513d9..416a14b 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -20,10 +20,12 @@ obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
# Tegra machine Support
snd-soc-tegra-wm8753-objs := tegra_wm8753.o
snd-soc-tegra-wm8903-objs := tegra_wm8903.o
+snd-soc-tegra-wm9712-objs := tegra_wm9712.o
snd-soc-tegra-trimslice-objs := trimslice.o
snd-soc-tegra-alc5632-objs := tegra_alc5632.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
+obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
new file mode 100644
index 0000000..9268621
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm9712.c
@@ -0,0 +1,179 @@
+/*
+ * tegra20_wm9712.c - Tegra machine ASoC driver for boards using WM9712 codec.
+ *
+ * Copyright 2012 Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
+ *
+ * Partly based on code copyright/by:
+ * Copyright 2011,2012 Toradex Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define DRV_NAME "tegra-snd-wm9712"
+
+struct tegra_wm9712 {
+ struct platform_device *codec;
+};
+
+static const struct snd_soc_dapm_widget tegra_wm9712_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_LINE("LineIn", NULL),
+ SND_SOC_DAPM_MIC("Mic", NULL),
+};
+
+static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int err;
+
+ snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
+
+ err = snd_soc_dapm_sync(dapm);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static struct snd_soc_dai_link tegra_wm9712_dai = {
+ .name = "AC97 HiFi",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai_name = "tegra-ac97-pcm",
+ .codec_dai_name = "wm9712-hifi",
+ .codec_name = "wm9712-codec",
+ .init = tegra_wm9712_init,
+};
+
+static struct snd_soc_card snd_soc_tegra_wm9712 = {
+ .name = "tegra-wm9712",
+ .owner = THIS_MODULE,
+ .dai_link = &tegra_wm9712_dai,
+ .num_links = 1,
+
+ .dapm_widgets = tegra_wm9712_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tegra_wm9712_dapm_widgets),
+ .fully_routed = true,
+};
+
+static int tegra_wm9712_driver_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct snd_soc_card *card = &snd_soc_tegra_wm9712;
+ struct tegra_wm9712 *machine;
+ int ret;
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "No platform data supplied\n");
+ return -EINVAL;
+ }
+
+ machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm9712),
+ GFP_KERNEL);
+ if (!machine) {
+ dev_err(&pdev->dev, "Can't allocate tegra_wm9712 struct\n");
+ return -ENOMEM;
+ }
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, machine);
+
+ machine->codec = platform_device_alloc("wm9712-codec", -1);
+ if (!machine->codec) {
+ dev_err(&pdev->dev, "Can't allocate wm9712 platform device\n");
+ return -ENOMEM;
+ }
+
+ ret = platform_device_add(machine->codec);
+ if (ret)
+ goto codec_put;
+
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto codec_put;
+
+ ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+ if (ret)
+ goto codec_put;
+
+ tegra_wm9712_dai.cpu_of_node = of_parse_phandle(np,
+ "nvidia,ac97-controller", 0);
+ if (!tegra_wm9712_dai.cpu_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,ac97-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto codec_put;
+ }
+
+ tegra_wm9712_dai.platform_of_node = tegra_wm9712_dai.cpu_of_node;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto codec_put;
+ }
+
+ return 0;
+
+codec_put:
+ platform_device_put(machine->codec);
+ return ret;
+}
+
+static int tegra_wm9712_driver_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct tegra_wm9712 *machine = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_card(card);
+
+ platform_device_put(machine->codec);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_wm9712_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-wm9712", },
+ {},
+};
+
+static struct platform_driver tegra_wm9712_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_wm9712_of_match,
+ },
+ .probe = tegra_wm9712_driver_probe,
+ .remove = tegra_wm9712_driver_remove,
+};
+module_platform_driver(tegra_wm9712_driver);
+
+MODULE_AUTHOR("Lucas Stach");
+MODULE_DESCRIPTION("Tegra+WM9712 machine ASoC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_wm9712_of_match);
--
1.8.0.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/3] ASoC: tegra: add ac97 host driver
[not found] ` <1357348725-32139-2-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
@ 2013-01-08 22:10 ` Stephen Warren
[not found] ` <50EC9953.1000107-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-01-13 23:21 ` Mark Brown
1 sibling, 1 reply; 18+ messages in thread
From: Stephen Warren @ 2013-01-08 22:10 UTC (permalink / raw)
To: Lucas Stach
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On 01/04/2013 06:18 PM, Lucas Stach wrote:
> This adds the driver for the Tegra 2x AC97 host controller.
>
> Signed-off-by: Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
> diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt
> +- nvidia,codec-sync-gpio : The Tegra GPIO controller's phandle and the number
> + of the GPIO corresponding with the AC97 DAP _FS line
> +Example:
If you have to repost for any reason, you probably want a blank line
before the "Example:" line.
> diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
> +static void tegra20_ac97_codec_warm_reset(struct snd_ac97 *ac97)
> +{
> + u32 readback;
> + unsigned long timeout;
> +
> + /*
> + * although sync line is driven by the DAC pad group warm reset using
> + * the controller cmd is not working, have to toggle sync line
> + * manually.
> + */
> + gpio_request(workdata->sync_gpio, "codec-sync");
> +
> + gpio_direction_output(workdata->sync_gpio, 1);
Would it make sense to just request the GPIO during probe()? Or, is the
sync signal used as part of the AC'97 protocol at other times?
> +static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97)
> +{
> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
> + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN,
> + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN);
> +
> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
> + TEGRA20_AC97_CTRL_PCM_DAC_EN |
> + TEGRA20_AC97_CTRL_STM_EN,
> + TEGRA20_AC97_CTRL_PCM_DAC_EN |
> + TEGRA20_AC97_CTRL_STM_EN);
> +}
That sets both PCM_DAC_EN and STM_EN, but ...
> +static inline void tegra20_ac97_stop_playback(struct tegra20_ac97 *ac97)
> +{
> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
> + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 0);
> +
> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
> + TEGRA20_AC97_CTRL_PCM_DAC_EN, 0);
> +}
... that only clears DAC_EN. Should it clear STM_EN too?
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree
[not found] ` <1357348725-32139-3-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
@ 2013-01-08 22:11 ` Stephen Warren
[not found] ` <50EC99A1.4080402-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
0 siblings, 1 reply; 18+ messages in thread
From: Stephen Warren @ 2013-01-08 22:11 UTC (permalink / raw)
To: Lucas Stach
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On 01/04/2013 06:18 PM, Lucas Stach wrote:
> Add default entry for the AC97 host controller.
This looks fine. I assume I'll take this through the Tegra tree.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 3/3] ASoC: tegra: add tegra machine driver using wm9712 codec
[not found] ` <1357348725-32139-4-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
@ 2013-01-08 22:17 ` Stephen Warren
[not found] ` <50EC9B01.6010203-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-01-16 12:05 ` [PATCH v3] " Lucas Stach
1 sibling, 1 reply; 18+ messages in thread
From: Stephen Warren @ 2013-01-08 22:17 UTC (permalink / raw)
To: Lucas Stach
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On 01/04/2013 06:18 PM, Lucas Stach wrote:
> This adds a very simple machine driver using the Wolfson wm9712 AC97
> codec.
> diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
> +static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
> + err = snd_soc_dapm_sync(dapm);
> + if (err)
> + return err;
> +
> + return 0;
That block is just "return snd_soc_dapm_sync(dapm);"
> +static int tegra_wm9712_driver_probe(struct platform_device *pdev)
> + machine->codec = platform_device_alloc("wm9712-codec", -1);
Hmmm. I thought that could be auto-instantiated based on probing the
AC'97 bus for whatever was there?
> + ret = platform_device_add(machine->codec);
> + if (ret)
> + goto codec_put;
After this point, ...
> + ret = snd_soc_of_parse_card_name(card, "nvidia,model");
> + if (ret)
> + goto codec_put;
don't the error paths need to undo platform_device_add()? Or does
platform_device_put() do that automatically?
> +codec_put:
> + platform_device_put(machine->codec);
> + return ret;
> +}
> +static int tegra_wm9712_driver_remove(struct platform_device *pdev)
> + platform_device_put(machine->codec);
Same comment here.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/3] ASoC: tegra: add ac97 host driver
[not found] ` <50EC9953.1000107-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-01-08 22:22 ` Lucas Stach
2013-01-08 22:27 ` Stephen Warren
0 siblings, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2013-01-08 22:22 UTC (permalink / raw)
To: Stephen Warren
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, linux-tegra-u79uwXL29TY76Z2rM5mHXA
Am Dienstag, den 08.01.2013, 15:10 -0700 schrieb Stephen Warren:
> On 01/04/2013 06:18 PM, Lucas Stach wrote:
> > This adds the driver for the Tegra 2x AC97 host controller.
> >
> > Signed-off-by: Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
>
> > diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt
>
> > +- nvidia,codec-sync-gpio : The Tegra GPIO controller's phandle and the number
> > + of the GPIO corresponding with the AC97 DAP _FS line
> > +Example:
>
> If you have to repost for any reason, you probably want a blank line
> before the "Example:" line.
>
> > diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
>
> > +static void tegra20_ac97_codec_warm_reset(struct snd_ac97 *ac97)
> > +{
> > + u32 readback;
> > + unsigned long timeout;
> > +
> > + /*
> > + * although sync line is driven by the DAC pad group warm reset using
> > + * the controller cmd is not working, have to toggle sync line
> > + * manually.
> > + */
> > + gpio_request(workdata->sync_gpio, "codec-sync");
> > +
> > + gpio_direction_output(workdata->sync_gpio, 1);
>
> Would it make sense to just request the GPIO during probe()? Or, is the
> sync signal used as part of the AC'97 protocol at other times?
Yes, the sync line is used during normal codec operation, that's why
it's explicitly requested and freed in the warm reset function. As
discussed earlier this is ugly, but unavoidable as the Tegra 2 AC97
controller misbehaves when ordered to do the warm reset. So this is just
a software hack to take over the line as a GPIO and do what the hardware
is supposed to do in this situation.
>
> > +static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97)
> > +{
> > + regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
> > + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN,
> > + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN);
> > +
> > + regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
> > + TEGRA20_AC97_CTRL_PCM_DAC_EN |
> > + TEGRA20_AC97_CTRL_STM_EN,
> > + TEGRA20_AC97_CTRL_PCM_DAC_EN |
> > + TEGRA20_AC97_CTRL_STM_EN);
> > +}
>
> That sets both PCM_DAC_EN and STM_EN, but ...
>
> > +static inline void tegra20_ac97_stop_playback(struct tegra20_ac97 *ac97)
> > +{
> > + regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
> > + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 0);
> > +
> > + regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
> > + TEGRA20_AC97_CTRL_PCM_DAC_EN, 0);
> > +}
>
> ... that only clears DAC_EN. Should it clear STM_EN too?
>
To be honest I have no idea what STM really is, seems to be some form of
packed format selection. If not set playback outputs only more or less
random noise. Only PCM_EN controls FIFO and DMA operations though, so
it's ok to just disable this to stop playback.
Regards,
Lucas
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/3] ASoC: tegra: add ac97 host driver
2013-01-08 22:22 ` Lucas Stach
@ 2013-01-08 22:27 ` Stephen Warren
0 siblings, 0 replies; 18+ messages in thread
From: Stephen Warren @ 2013-01-08 22:27 UTC (permalink / raw)
To: Lucas Stach
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On 01/08/2013 03:22 PM, Lucas Stach wrote:
> Am Dienstag, den 08.01.2013, 15:10 -0700 schrieb Stephen Warren:
>> On 01/04/2013 06:18 PM, Lucas Stach wrote:
>>> This adds the driver for the Tegra 2x AC97 host controller.
>>> diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
>>> +static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97)
>>> +{
>>> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
>>> + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN,
>>> + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN);
>>> +
>>> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
>>> + TEGRA20_AC97_CTRL_PCM_DAC_EN |
>>> + TEGRA20_AC97_CTRL_STM_EN,
>>> + TEGRA20_AC97_CTRL_PCM_DAC_EN |
>>> + TEGRA20_AC97_CTRL_STM_EN);
>>> +}
>>
>> That sets both PCM_DAC_EN and STM_EN, but ...
>>
>>> +static inline void tegra20_ac97_stop_playback(struct tegra20_ac97 *ac97)
>>> +{
>>> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
>>> + TEGRA20_AC97_FIFO_SCR_PB_QRT_MT_EN, 0);
>>> +
>>> + regmap_update_bits(ac97->regmap, TEGRA20_AC97_CTRL,
>>> + TEGRA20_AC97_CTRL_PCM_DAC_EN, 0);
>>> +}
>>
>> ... that only clears DAC_EN. Should it clear STM_EN too?
>>
> To be honest I have no idea what STM really is, seems to be some form of
> packed format selection. If not set playback outputs only more or less
> random noise. Only PCM_EN controls FIFO and DMA operations though, so
> it's ok to just disable this to stop playback.
I'd be tempted to just hard-code those bits on in probe() then, but it's
not a big deal, so not worth spinning the patch for that.
I guess I meant to say,
Reviewed-by: Stephen Warren <swarren-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 3/3] ASoC: tegra: add tegra machine driver using wm9712 codec
[not found] ` <50EC9B01.6010203-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-01-08 22:52 ` Lucas Stach
2013-01-13 23:26 ` Mark Brown
0 siblings, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2013-01-08 22:52 UTC (permalink / raw)
To: Stephen Warren
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, linux-tegra-u79uwXL29TY76Z2rM5mHXA
Am Dienstag, den 08.01.2013, 15:17 -0700 schrieb Stephen Warren:
> On 01/04/2013 06:18 PM, Lucas Stach wrote:
> > This adds a very simple machine driver using the Wolfson wm9712 AC97
> > codec.
>
> > diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
>
>
> > +static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
>
> > + err = snd_soc_dapm_sync(dapm);
> > + if (err)
> > + return err;
> > +
> > + return 0;
>
> That block is just "return snd_soc_dapm_sync(dapm);"
>
> > +static int tegra_wm9712_driver_probe(struct platform_device *pdev)
>
> > + machine->codec = platform_device_alloc("wm9712-codec", -1);
>
> Hmmm. I thought that could be auto-instantiated based on probing the
> AC'97 bus for whatever was there?
AC97 is in principle probeable by reading the first regs of the codec,
but all the infrastructure to do proper hotplugging on the AC97 bus is
missing in the kernel. As I didn't want to be the one to add all this
infrastructure to a dying audio platform, I opted to do the same thing
as all the other platform using AC97 and instantiate the codec from the
machine driver.
This binds machine driver and codec together, but after all the machine
driver is already both pretty small and codec specific. So considering
the number of Tegra platform out there using AC97 I figured it's not
worth the hassle trying to write a generic machine driver.
>
> > + ret = platform_device_add(machine->codec);
> > + if (ret)
> > + goto codec_put;
>
> After this point, ...
>
> > + ret = snd_soc_of_parse_card_name(card, "nvidia,model");
> > + if (ret)
> > + goto codec_put;
>
> don't the error paths need to undo platform_device_add()? Or does
> platform_device_put() do that automatically?
>
Yep, I've just gone through the implementation of those platform
functions and at some point we reverse the device_add. I'll fix this up.
> > +codec_put:
> > + platform_device_put(machine->codec);
> > + return ret;
> > +}
>
> > +static int tegra_wm9712_driver_remove(struct platform_device *pdev)
>
> > + platform_device_put(machine->codec);
>
> Same comment here.
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/3] ASoC: tegra: add ac97 host driver
[not found] ` <1357348725-32139-2-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-08 22:10 ` Stephen Warren
@ 2013-01-13 23:21 ` Mark Brown
1 sibling, 0 replies; 18+ messages in thread
From: Mark Brown @ 2013-01-13 23:21 UTC (permalink / raw)
To: Lucas Stach
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Stephen Warren, linux-tegra-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 142 bytes --]
On Sat, Jan 05, 2013 at 02:18:43AM +0100, Lucas Stach wrote:
> This adds the driver for the Tegra 2x AC97 host controller.
Applied, thanks.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree
[not found] ` <50EC99A1.4080402-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-01-13 23:22 ` Mark Brown
[not found] ` <20130113232222.GN5041-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
0 siblings, 1 reply; 18+ messages in thread
From: Mark Brown @ 2013-01-13 23:22 UTC (permalink / raw)
To: Stephen Warren
Cc: Lucas Stach, alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, linux-tegra-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 249 bytes --]
On Tue, Jan 08, 2013 at 03:11:45PM -0700, Stephen Warren wrote:
> On 01/04/2013 06:18 PM, Lucas Stach wrote:
> > Add default entry for the AC97 host controller.
> This looks fine. I assume I'll take this through the Tegra tree.
Makes sense to me.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 3/3] ASoC: tegra: add tegra machine driver using wm9712 codec
2013-01-08 22:52 ` Lucas Stach
@ 2013-01-13 23:26 ` Mark Brown
0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2013-01-13 23:26 UTC (permalink / raw)
To: Lucas Stach
Cc: Stephen Warren, alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, linux-tegra-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 996 bytes --]
On Tue, Jan 08, 2013 at 11:52:33PM +0100, Lucas Stach wrote:
> Am Dienstag, den 08.01.2013, 15:17 -0700 schrieb Stephen Warren:
> > Hmmm. I thought that could be auto-instantiated based on probing the
> > AC'97 bus for whatever was there?
> AC97 is in principle probeable by reading the first regs of the codec,
> but all the infrastructure to do proper hotplugging on the AC97 bus is
> missing in the kernel. As I didn't want to be the one to add all this
> infrastructure to a dying audio platform, I opted to do the same thing
> as all the other platform using AC97 and instantiate the codec from the
> machine driver.
That's about the size of it, yes. We should write the device tree as
though we'd got better infrastructure here since this isn't something
that ought to be required but right now this is how you do AC'97 in
ASoC. It'd be really nice if someone had the time to work on the AC'97
infrastructure here but I'd not hold my breath given that it's rarely
used in new designs.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree
[not found] ` <20130113232222.GN5041-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
@ 2013-01-14 17:00 ` Stephen Warren
[not found] ` <50F439C0.4080603-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
0 siblings, 1 reply; 18+ messages in thread
From: Stephen Warren @ 2013-01-14 17:00 UTC (permalink / raw)
To: Mark Brown
Cc: Lucas Stach, alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On 01/13/2013 04:22 PM, Mark Brown wrote:
> On Tue, Jan 08, 2013 at 03:11:45PM -0700, Stephen Warren wrote:
>> On 01/04/2013 06:18 PM, Lucas Stach wrote:
>>> Add default entry for the AC97 host controller.
>
>> This looks fine. I assume I'll take this through the Tegra tree.
>
> Makes sense to me.
Thanks, applied to Tegra's for-3.9/dt branch.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree
[not found] ` <50F439C0.4080603-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
@ 2013-01-14 17:22 ` Stephen Warren
0 siblings, 0 replies; 18+ messages in thread
From: Stephen Warren @ 2013-01-14 17:22 UTC (permalink / raw)
To: Mark Brown
Cc: Lucas Stach, alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On 01/14/2013 10:00 AM, Stephen Warren wrote:
> On 01/13/2013 04:22 PM, Mark Brown wrote:
>> On Tue, Jan 08, 2013 at 03:11:45PM -0700, Stephen Warren wrote:
>>> On 01/04/2013 06:18 PM, Lucas Stach wrote:
>>>> Add default entry for the AC97 host controller.
>>
>>> This looks fine. I assume I'll take this through the Tegra tree.
>>
>> Makes sense to me.
>
> Thanks, applied to Tegra's for-3.9/dt branch.
I had to make a small modification to the patch; I commented out the
clocks property for now since the CAR node isn't yet present. It will be
soon once the common clock framework patches are merged, and then I'll
revert the change I made.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3] ASoC: tegra: add tegra machine driver using wm9712 codec
[not found] ` <1357348725-32139-4-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-08 22:17 ` Stephen Warren
@ 2013-01-16 12:05 ` Lucas Stach
[not found] ` <1358337912-27673-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
1 sibling, 1 reply; 18+ messages in thread
From: Lucas Stach @ 2013-01-16 12:05 UTC (permalink / raw)
To: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, Stephen Warren,
linux-tegra-u79uwXL29TY76Z2rM5mHXA
This adds a very simple machine driver using the Wolfson wm9712 AC97
codec.
Signed-off-by: Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
---
v2:
- manually probe codec driver without using DT
- fixup Kconfig for select and depends
v3:
- correctly tear down codec platform device in error and remove paths
- simplify init function
---
.../bindings/sound/nvidia,tegra-audio-wm9712.txt | 51 ++++++
sound/soc/tegra/Kconfig | 9 ++
sound/soc/tegra/Makefile | 2 +
sound/soc/tegra/tegra_wm9712.c | 176 +++++++++++++++++++++
4 files changed, 238 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
create mode 100644 sound/soc/tegra/tegra_wm9712.c
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
new file mode 100644
index 0000000..be35d34
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm9712.txt
@@ -0,0 +1,51 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-wm9712"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source. Valid names for sources and
+ sinks are the WM9712's pins, and the jacks on the board:
+
+ WM9712 pins:
+
+ * MONOOUT
+ * HPOUTL
+ * HPOUTR
+ * LOUT2
+ * ROUT2
+ * OUT3
+ * LINEINL
+ * LINEINR
+ * PHONE
+ * PCBEEP
+ * MIC1
+ * MIC2
+ * Mic Bias
+
+ Board connectors:
+
+ * Headphone
+ * LineIn
+ * Mic
+
+- nvidia,ac97-controller : The phandle of the Tegra AC97 controller
+
+
+Example:
+
+sound {
+ compatible = "nvidia,tegra-audio-wm9712-colibri_t20",
+ "nvidia,tegra-audio-wm9712";
+ nvidia,model = "Toradex Colibri T20";
+
+ nvidia,audio-routing =
+ "Headphone", "HPOUTL",
+ "Headphone", "HPOUTR",
+ "LineIn", "LINEINL",
+ "LineIn", "LINEINR",
+ "Mic", "MIC1";
+
+ nvidia,ac97-controller = <&ac97>;
+};
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 19e5fe7..2cb45d0 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -70,6 +70,15 @@ config SND_SOC_TEGRA_WM8903
boards using the WM8093 codec. Currently, the supported boards are
Harmony, Ventana, Seaboard, Kaen, and Aebl.
+config SND_SOC_TEGRA_WM9712
+ tristate "SoC Audio support for Tegra boards using a WM9712 codec"
+ depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA20_AC97
+ select SND_SOC_WM9712
+ help
+ Say Y or M here if you want to add support for SoC audio on Tegra
+ boards using the WM9712 (or compatible) codec.
+
config SND_SOC_TEGRA_TRIMSLICE
tristate "SoC Audio support for TrimSlice board"
depends on SND_SOC_TEGRA && I2C
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 391e78a..6ef663f 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -18,10 +18,12 @@ obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
# Tegra machine Support
snd-soc-tegra-wm8753-objs := tegra_wm8753.o
snd-soc-tegra-wm8903-objs := tegra_wm8903.o
+snd-soc-tegra-wm9712-objs := tegra_wm9712.o
snd-soc-tegra-trimslice-objs := trimslice.o
snd-soc-tegra-alc5632-objs := tegra_alc5632.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
+obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c
new file mode 100644
index 0000000..cdbd2f0
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm9712.c
@@ -0,0 +1,176 @@
+/*
+ * tegra20_wm9712.c - Tegra machine ASoC driver for boards using WM9712 codec.
+ *
+ * Copyright 2012 Lucas Stach <dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
+ *
+ * Partly based on code copyright/by:
+ * Copyright 2011,2012 Toradex Inc.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define DRV_NAME "tegra-snd-wm9712"
+
+struct tegra_wm9712 {
+ struct platform_device *codec;
+};
+
+static const struct snd_soc_dapm_widget tegra_wm9712_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_LINE("LineIn", NULL),
+ SND_SOC_DAPM_MIC("Mic", NULL),
+};
+
+static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
+
+ return snd_soc_dapm_sync(dapm);
+}
+
+static struct snd_soc_dai_link tegra_wm9712_dai = {
+ .name = "AC97 HiFi",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai_name = "tegra-ac97-pcm",
+ .codec_dai_name = "wm9712-hifi",
+ .codec_name = "wm9712-codec",
+ .init = tegra_wm9712_init,
+};
+
+static struct snd_soc_card snd_soc_tegra_wm9712 = {
+ .name = "tegra-wm9712",
+ .owner = THIS_MODULE,
+ .dai_link = &tegra_wm9712_dai,
+ .num_links = 1,
+
+ .dapm_widgets = tegra_wm9712_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tegra_wm9712_dapm_widgets),
+ .fully_routed = true,
+};
+
+static int tegra_wm9712_driver_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct snd_soc_card *card = &snd_soc_tegra_wm9712;
+ struct tegra_wm9712 *machine;
+ int ret;
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "No platform data supplied\n");
+ return -EINVAL;
+ }
+
+ machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm9712),
+ GFP_KERNEL);
+ if (!machine) {
+ dev_err(&pdev->dev, "Can't allocate tegra_wm9712 struct\n");
+ return -ENOMEM;
+ }
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, machine);
+
+ machine->codec = platform_device_alloc("wm9712-codec", -1);
+ if (!machine->codec) {
+ dev_err(&pdev->dev, "Can't allocate wm9712 platform device\n");
+ return -ENOMEM;
+ }
+
+ ret = platform_device_add(machine->codec);
+ if (ret)
+ goto codec_put;
+
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto codec_unregister;
+
+ ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+ if (ret)
+ goto codec_unregister;
+
+ tegra_wm9712_dai.cpu_of_node = of_parse_phandle(np,
+ "nvidia,ac97-controller", 0);
+ if (!tegra_wm9712_dai.cpu_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,ac97-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto codec_unregister;
+ }
+
+ tegra_wm9712_dai.platform_of_node = tegra_wm9712_dai.cpu_of_node;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto codec_unregister;
+ }
+
+ return 0;
+
+codec_unregister:
+ platform_device_del(machine->codec);
+codec_put:
+ platform_device_put(machine->codec);
+ return ret;
+}
+
+static int tegra_wm9712_driver_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct tegra_wm9712 *machine = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_card(card);
+
+ platform_device_unregister(machine->codec);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_wm9712_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-wm9712", },
+ {},
+};
+
+static struct platform_driver tegra_wm9712_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_wm9712_of_match,
+ },
+ .probe = tegra_wm9712_driver_probe,
+ .remove = tegra_wm9712_driver_remove,
+};
+module_platform_driver(tegra_wm9712_driver);
+
+MODULE_AUTHOR("Lucas Stach");
+MODULE_DESCRIPTION("Tegra+WM9712 machine ASoC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_wm9712_of_match);
--
1.8.0.2
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v3] ASoC: tegra: add tegra machine driver using wm9712 codec
[not found] ` <1358337912-27673-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
@ 2013-01-16 22:00 ` Stephen Warren
2013-01-17 7:02 ` Mark Brown
1 sibling, 0 replies; 18+ messages in thread
From: Stephen Warren @ 2013-01-16 22:00 UTC (permalink / raw)
To: Lucas Stach
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Mark Brown, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On 01/16/2013 05:05 AM, Lucas Stach wrote:
> This adds a very simple machine driver using the Wolfson wm9712 AC97
> codec.
Reviewed-by: Stephen Warren <swarren-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v3] ASoC: tegra: add tegra machine driver using wm9712 codec
[not found] ` <1358337912-27673-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-16 22:00 ` Stephen Warren
@ 2013-01-17 7:02 ` Mark Brown
1 sibling, 0 replies; 18+ messages in thread
From: Mark Brown @ 2013-01-17 7:02 UTC (permalink / raw)
To: Lucas Stach
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
patches-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
Liam Girdwood, Stephen Warren, linux-tegra-u79uwXL29TY76Z2rM5mHXA
On Wed, Jan 16, 2013 at 01:05:12PM +0100, Lucas Stach wrote:
> This adds a very simple machine driver using the Wolfson wm9712 AC97
> codec.
Applied, thanks.
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2013-01-17 7:02 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-05 1:18 [PATCH v2 0/3] Tegra AC97 v2 Lucas Stach
[not found] ` <1357348725-32139-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-05 1:18 ` [PATCH v2 1/3] ASoC: tegra: add ac97 host driver Lucas Stach
[not found] ` <1357348725-32139-2-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-08 22:10 ` Stephen Warren
[not found] ` <50EC9953.1000107-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-01-08 22:22 ` Lucas Stach
2013-01-08 22:27 ` Stephen Warren
2013-01-13 23:21 ` Mark Brown
2013-01-05 1:18 ` [PATCH v2 2/3] ASoC: tegra: add ac97 host controller to device tree Lucas Stach
[not found] ` <1357348725-32139-3-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-08 22:11 ` Stephen Warren
[not found] ` <50EC99A1.4080402-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-01-13 23:22 ` Mark Brown
[not found] ` <20130113232222.GN5041-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org>
2013-01-14 17:00 ` Stephen Warren
[not found] ` <50F439C0.4080603-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-01-14 17:22 ` Stephen Warren
2013-01-05 1:18 ` [PATCH v2 3/3] ASoC: tegra: add tegra machine driver using wm9712 codec Lucas Stach
[not found] ` <1357348725-32139-4-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-08 22:17 ` Stephen Warren
[not found] ` <50EC9B01.6010203-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-01-08 22:52 ` Lucas Stach
2013-01-13 23:26 ` Mark Brown
2013-01-16 12:05 ` [PATCH v3] " Lucas Stach
[not found] ` <1358337912-27673-1-git-send-email-dev-8ppwABl0HbeELgA04lAiVw@public.gmane.org>
2013-01-16 22:00 ` Stephen Warren
2013-01-17 7:02 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).