diff mbox

[v11,3/8] ASoC: generic: simple DT sound card

Message ID 1376924761-4054-4-git-send-email-mpa@pengutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Markus Pargmann Aug. 19, 2013, 3:05 p.m. UTC
Simple sound card initialized using DT. When used with AC97, ac97-codec
is used to automatically discover the used codec.

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 .../bindings/sound/generic,simple-dt-card.txt      |  28 ++++
 sound/soc/generic/Kconfig                          |   1 +
 sound/soc/generic/Makefile                         |   3 +-
 sound/soc/generic/simple-dt-card.c                 | 186 +++++++++++++++++++++
 4 files changed, 217 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/sound/generic,simple-dt-card.txt
 create mode 100644 sound/soc/generic/simple-dt-card.c

Comments

Mark Brown Aug. 23, 2013, 9:58 a.m. UTC | #1
On Mon, Aug 19, 2013 at 05:05:56PM +0200, Markus Pargmann wrote:
> Simple sound card initialized using DT. When used with AC97, ac97-codec
> is used to automatically discover the used codec.

I've held back a bit on this one.  The reason is that it's adding a
separate card to the generic card which doesn't seem like the obvious
thing to do - obviously they have very similar goals, it's just that one
is for DT usage and the other isn't.  What's the reason for not adding
DT support to the generic card?
Markus Pargmann Aug. 31, 2013, 7:17 a.m. UTC | #2
Hi,

On Fri, Aug 23, 2013 at 10:58:16AM +0100, Mark Brown wrote:
> On Mon, Aug 19, 2013 at 05:05:56PM +0200, Markus Pargmann wrote:
> > Simple sound card initialized using DT. When used with AC97, ac97-codec
> > is used to automatically discover the used codec.
> 
> I've held back a bit on this one.  The reason is that it's adding a
> separate card to the generic card which doesn't seem like the obvious
> thing to do - obviously they have very similar goals, it's just that one
> is for DT usage and the other isn't.  What's the reason for not adding
> DT support to the generic card?

There was no code I could reuse from the existing simple card driver, so
I decided to seperate the DT part.

I will move the DT driver code into simple card and resend the patch.

Thanks,

Markus
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/sound/generic,simple-dt-card.txt b/Documentation/devicetree/bindings/sound/generic,simple-dt-card.txt
new file mode 100644
index 0000000..189d754
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/generic,simple-dt-card.txt
@@ -0,0 +1,28 @@ 
+Simple DT card
+
+A simple generic driver that connects a CPU DAI with a CODEC.
+
+Required properties:
+ - compatible: "asoc-simple-dt-card" used for standard ssi, codec
+   combinations, or "asoc-simple-ac97-dt-card" to use ac97 to discover the
+   codec.
+ - cpu-dai: CPU DAI connected to the codec.
+
+Required properties for "asoc-simple-dt-card":
+ - audio-codec: Codec phandle.
+ - codec-dai-name: DAI name within the codec.
+
+Examples:
+
+sound {
+	compatible = "asoc-simple-dt-card";
+	cpu-dai = <&ssi1>;
+	audio-codec = <&wm9712>;
+};
+
+For AC97:
+
+sound {
+	compatible = "asoc-simple-ac97-dt-card";
+	cpu-dai = <&ssi1>;
+};
diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig
index 610f612..8718ac6 100644
--- a/sound/soc/generic/Kconfig
+++ b/sound/soc/generic/Kconfig
@@ -1,4 +1,5 @@ 
 config SND_SIMPLE_CARD
 	tristate "ASoC Simple sound card support"
+	select SND_SOC_AC97_BUS
 	help
 	  This option enables generic simple sound card support
diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile
index 9c3b246..9ccf864 100644
--- a/sound/soc/generic/Makefile
+++ b/sound/soc/generic/Makefile
@@ -1,3 +1,4 @@ 
 snd-soc-simple-card-objs	:= simple-card.o
+snd-soc-simple-dt-card-objs	:= simple-dt-card.o
 
-obj-$(CONFIG_SND_SIMPLE_CARD)	+= snd-soc-simple-card.o
+obj-$(CONFIG_SND_SIMPLE_CARD)	+= snd-soc-simple-card.o snd-soc-simple-dt-card.o
diff --git a/sound/soc/generic/simple-dt-card.c b/sound/soc/generic/simple-dt-card.c
new file mode 100644
index 0000000..532be0f
--- /dev/null
+++ b/sound/soc/generic/simple-dt-card.c
@@ -0,0 +1,186 @@ 
+/*
+ * phycore-ac97-dt.c  --  SoC audio for imx_phycore in AC97 mode
+ *
+ * Copyright 2013 Markus Pargmann, Pengutronix <mpa@pengutronix.de>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+struct simple_dt_card_data {
+	struct snd_soc_dai_link link;
+	struct snd_soc_card card;
+	struct device_node *cpu_np;
+	struct device_node *codec_np;
+	struct platform_device *ac97_codec;
+};
+
+static struct snd_soc_dai_link simple_ac97_dt_card_dai = {
+	.name		= "HiFi",
+	.stream_name	= "HiFi",
+	.codec_dai_name	= "ac97-hifi",
+	.codec_name	= "ac97-codec",
+};
+
+static const struct snd_soc_card simple_ac97_dt_card = {
+	.name		= "ASoC simple AC97 DT card",
+	.owner		= THIS_MODULE,
+};
+
+static struct snd_soc_dai_link simple_dt_card_dai = {
+	.name		= "simple-link",
+	.stream_name	= "simple-link",
+};
+
+static const struct snd_soc_card simple_dt_card = {
+	.name		= "ASoC simple DT card",
+	.owner		= THIS_MODULE,
+};
+
+enum simple_dt_card_type {
+	SIMPLE_CARD,
+	SIMPLE_CARD_AC97,
+};
+
+static const struct of_device_id simple_dt_card_of_dev_ids[] = {
+	{
+		.compatible = "asoc-simple-dt-card",
+		.data = (void *)SIMPLE_CARD,
+	}, {
+		.compatible = "asoc-simple-ac97-dt-card",
+		.data = (void *)SIMPLE_CARD_AC97,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, simple_dt_card_of_dev_id);
+
+static int simple_dt_card_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+			of_match_device(simple_dt_card_of_dev_ids, &pdev->dev);
+	enum simple_dt_card_type type = (enum simple_dt_card_type)of_id->data;
+	int ret;
+	struct simple_dt_card_data *priv;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+
+	if (!priv)
+		return -ENOMEM;
+
+	priv->card.dev = &pdev->dev;
+
+	priv->cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);
+	if (!priv->cpu_np) {
+		dev_err(&pdev->dev, "No valid CPU DAI phandle found\n");
+		return -EINVAL;
+	}
+
+	if (type == SIMPLE_CARD_AC97) {
+		struct platform_device *ac97_codec;
+		memcpy(&priv->card, &simple_ac97_dt_card,
+				sizeof(simple_ac97_dt_card));
+		memcpy(&priv->link, &simple_ac97_dt_card_dai,
+				sizeof(simple_ac97_dt_card_dai));
+
+		ac97_codec = platform_device_register_simple("ac97-codec", -1,
+				NULL, 0);
+		if (IS_ERR(ac97_codec)) {
+			dev_err(&pdev->dev, "Failed to register ac97-codec device\n");
+			ret = PTR_ERR(priv->ac97_codec);
+			goto err;
+		}
+		priv->ac97_codec = ac97_codec;
+	} else {
+		priv->codec_np = of_parse_phandle(pdev->dev.of_node,
+				"audio-codec", 0);
+		if (!priv->codec_np) {
+			dev_err(&pdev->dev, "No valid codec phandle found\n");
+			ret = -EINVAL;
+			goto err;
+		}
+
+		memcpy(&priv->link, &simple_dt_card_dai,
+				sizeof(simple_dt_card_dai));
+		memcpy(&priv->card, &simple_dt_card, sizeof(simple_dt_card));
+		priv->link.codec_of_node = priv->codec_np;
+
+		ret = of_property_read_string(pdev->dev.of_node,
+				"codec-dai-name", &priv->link.stream_name);
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to parse codec-dai-name string\n");
+			ret = -EINVAL;
+			goto err;
+		}
+	}
+
+	priv->link.cpu_of_node = priv->cpu_np;
+	priv->link.platform_of_node = priv->cpu_np;
+
+	priv->card.dai_link = &priv->link;
+	priv->card.num_links = 1;
+	priv->card.dev = &pdev->dev;
+
+	ret = snd_soc_register_card(&priv->card);
+	if (ret) {
+		dev_err(&pdev->dev, "ASoC: soc card registration failed\n");
+		goto err;
+	}
+
+	dev_set_drvdata(&pdev->dev, priv);
+
+	return 0;
+
+err:
+	if (priv->cpu_np)
+		of_node_put(priv->cpu_np);
+	if (priv->codec_np)
+		of_node_put(priv->codec_np);
+	if (priv->ac97_codec)
+		platform_device_unregister(priv->ac97_codec);
+	return ret;
+}
+
+static int simple_dt_card_remove(struct platform_device *pdev)
+{
+	struct simple_dt_card_data *priv = dev_get_drvdata(&pdev->dev);
+
+	snd_soc_unregister_card(&priv->card);
+
+	if (priv->cpu_np)
+		of_node_put(priv->cpu_np);
+	if (priv->codec_np)
+		of_node_put(priv->codec_np);
+	if (priv->ac97_codec)
+		platform_device_unregister(priv->ac97_codec);
+
+	return 0;
+}
+
+static struct platform_driver simple_dt_card_driver = {
+	.probe		= simple_dt_card_probe,
+	.remove		= simple_dt_card_remove,
+	.driver		= {
+		.name	= "asoc-simple-dt-card",
+		.owner	= THIS_MODULE,
+		.of_match_table = simple_dt_card_of_dev_ids,
+	},
+};
+
+module_platform_driver(simple_dt_card_driver);
+
+MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
+MODULE_DESCRIPTION("ASoC Simple DT Sound Card");
+MODULE_LICENSE("GPL");