All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jon Smirl <jonsmirl@gmail.com>
To: grant.likely@secretlab.ca, broonie@sirena.org.uk
Cc: alsa-devel@alsa-project.org
Subject: [PATCH V1 06/13] Allow a custom ASOC fabric driver with soc-of-simple
Date: Wed, 13 May 2009 21:59:12 -0400	[thread overview]
Message-ID: <20090514015912.28145.22291.stgit@terra> (raw)
In-Reply-To: <20090514015729.28145.30483.stgit@terra>

Allow a custom ASOC fabric driver with soc-of-simple. Register multiple DAIs. If no custom fabric driver, supply a default one so that ASOC binding will complete.

Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
 include/sound/soc-of-simple.h   |   16 +++-
 sound/last.c                    |    6 +
 sound/soc/codecs/tlv320aic26.c  |    2 
 sound/soc/fsl/Kconfig           |    2 
 sound/soc/fsl/mpc5200_psc_i2s.c |    4 -
 sound/soc/fsl/soc-of-simple.c   |  160 ++++++++++++++++++++++++++++++++-------
 6 files changed, 154 insertions(+), 36 deletions(-)

diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h
index a064e19..97d04af 100644
--- a/include/sound/soc-of-simple.h
+++ b/include/sound/soc-of-simple.h
@@ -12,13 +12,21 @@
 #include <linux/of.h>
 #include <sound/soc.h>
 
+#define SOC_OF_SIMPLE_MAX_DAI 2
+
 int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
 			      void *codec_data, struct snd_soc_dai *dai,
-			      struct device_node *node);
+			      int count, struct device_node *node);
+
+int of_snd_soc_register_cpu_dai(struct device_node *node,
+				 struct snd_soc_dai *cpu_dai, int count);
+
+int of_snd_soc_register_platform(struct snd_soc_platform *platform);
+
+int of_snd_soc_register_fabric(const char *name, struct snd_soc_ops *ops,
+								int (*init)(struct snd_soc_codec *codec));
 
-int of_snd_soc_register_platform(struct snd_soc_platform *platform,
-				 struct device_node *node,
-				 struct snd_soc_dai *cpu_dai);
+int of_snd_soc_register_default_fabric(void);
 
 #endif
 
diff --git a/sound/last.c b/sound/last.c
index bdd0857..b6efece 100644
--- a/sound/last.c
+++ b/sound/last.c
@@ -22,11 +22,15 @@
 #define SNDRV_MAIN_OBJECT_FILE
 #include <linux/init.h>
 #include <sound/core.h>
+#include <sound/soc-of-simple.h>
 
 static int __init alsa_sound_last_init(void)
 {
 	int idx, ok = 0;
-	
+
+#if defined(CONFIG_SND_SOC_OF_SIMPLE)
+	of_snd_soc_register_default_fabric();
+#endif 	
 	printk(KERN_INFO "ALSA device list:\n");
 	for (idx = 0; idx < SNDRV_CARDS; idx++)
 		if (snd_cards[idx] != NULL) {
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 3387d9e..95a7ac9 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -487,7 +487,7 @@ static int aic26_spi_probe(struct spi_device *spi)
 
 #if defined(CONFIG_SND_SOC_OF_SIMPLE)
 	/* Tell the of_soc helper about this codec */
-	of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai,
+	of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, 1,
 				  spi->dev.archdata.of_node);
 #endif
 
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index dc79bdf..8060b95 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,5 +1,5 @@
 config SND_SOC_OF_SIMPLE
-	tristate
+	bool
 	
 config SND_MPC52xx_DMA
 	tristate
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 12a7917..5dbf1bc 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -353,8 +353,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op,
 	snd_soc_register_platform(&psc_dma_pcm_soc_platform);
 
 	/* Tell the ASoC OF helpers about it */
-	of_snd_soc_register_platform(&psc_dma_pcm_soc_platform, op->node,
-				     &psc_dma->dai);
+	of_snd_soc_register_platform(&mpc5200_audio_dma_platform);
+	of_snd_soc_register_cpu_dai(op->node, &psc_dma->dai, 1);
 
 	return 0;
 }
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
index 8bc5cd9..bf307aa 100644
--- a/sound/soc/fsl/soc-of-simple.c
+++ b/sound/soc/fsl/soc-of-simple.c
@@ -32,18 +32,23 @@ struct of_snd_soc_device {
 	struct list_head list;
 	struct snd_soc_device device;
 	struct snd_soc_card card;
-	struct snd_soc_dai_link dai_link;
+	struct snd_soc_dai_link dai_link[SOC_OF_SIMPLE_MAX_DAI];
 	struct platform_device *pdev;
-	struct device_node *platform_node;
+	struct device_node *cpu_dai_node;
 	struct device_node *codec_node;
 };
 
-static struct snd_soc_ops of_snd_soc_ops = {
-};
+/* template values */
+struct snd_soc_platform *template_platform;
+const char *template_name = NULL;
+struct snd_soc_ops *template_ops;
+int (*template_init)(struct snd_soc_codec *codec);
 
 static struct of_snd_soc_device *
 of_snd_soc_get_device(struct device_node *codec_node)
 {
+	int i;
+
 	struct of_snd_soc_device *of_soc;
 
 	list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
@@ -58,10 +63,16 @@ of_snd_soc_get_device(struct device_node *codec_node)
 	/* Initialize the structure and add it to the global list */
 	of_soc->codec_node = codec_node;
 	of_soc->id = of_snd_soc_next_index++;
-	of_soc->card.dai_link = &of_soc->dai_link;
-	of_soc->card.num_links = 1;
+	of_soc->card.dai_link = of_soc->dai_link;
 	of_soc->device.card = &of_soc->card;
-	of_soc->dai_link.ops = &of_snd_soc_ops;
+	of_soc->card.num_links = SOC_OF_SIMPLE_MAX_DAI;
+	for (i = 0; i < SOC_OF_SIMPLE_MAX_DAI; i++) {
+		of_soc->dai_link[i].ops = template_ops;
+		of_soc->dai_link[i].init = template_init;
+	}
+	of_soc->card.name = (char *)template_name;
+	of_soc->card.platform = template_platform;
+
 	list_add(&of_soc->list, &of_snd_soc_device_list);
 
 	return of_soc;
@@ -74,10 +85,11 @@ static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc)
 
 	/* Only register the device if both the codec and platform have
 	 * been registered */
-	if ((!of_soc->device.codec_data) || (!of_soc->platform_node))
+	if ((!of_soc->device.codec_data) || (!of_soc->cpu_dai_node) ||
+									!of_soc->card.platform || !of_soc->card.name)
 		return;
 
-	pr_info("platform<-->codec match achieved; registering machine\n");
+	pr_info("platform<-->codec match achieved; registering fabric\n");
 
 	pdev = platform_device_alloc("soc-audio", of_soc->id);
 	if (!pdev) {
@@ -100,10 +112,10 @@ static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc)
 
 int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
 			      void *codec_data, struct snd_soc_dai *dai,
-			      struct device_node *node)
+			      int count, struct device_node *node)
 {
 	struct of_snd_soc_device *of_soc;
-	int rc = 0;
+	int i, rc = 0;
 
 	pr_info("registering ASoC codec driver: %s\n", node->full_name);
 
@@ -117,10 +129,11 @@ int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
 	/* Store the codec data */
 	of_soc->device.codec_data = codec_data;
 	of_soc->device.codec_dev = codec_dev;
-	of_soc->dai_link.name = (char *)node->name;
-	of_soc->dai_link.stream_name = (char *)node->name;
-	of_soc->dai_link.codec_dai = dai;
-
+	of_soc->card.num_links = min(count, of_soc->card.num_links);
+	for (i = 0; i < of_soc->card.num_links; i++) {
+		of_soc->dai_link[i].name = dai[i].name;
+		of_soc->dai_link[i].codec_dai = &dai[i];
+	}
 	/* Now try to register the SoC device */
 	of_snd_soc_register_device(of_soc);
 
@@ -130,21 +143,51 @@ int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
 }
 EXPORT_SYMBOL_GPL(of_snd_soc_register_codec);
 
-int of_snd_soc_register_platform(struct snd_soc_platform *platform,
-				 struct device_node *node,
-				 struct snd_soc_dai *cpu_dai)
+int of_snd_soc_register_cpu_dai(struct device_node *node,
+				 struct snd_soc_dai *cpu_dai, int count)
 {
 	struct of_snd_soc_device *of_soc;
 	struct device_node *codec_node;
 	const phandle *handle;
-	int len, rc = 0;
+	int i, len, rc = 0;
 
-	pr_info("registering ASoC platform driver: %s\n", node->full_name);
+	pr_info("registering ASoC CPU DAI driver: %s\n", node->full_name);
 
 	handle = of_get_property(node, "codec-handle", &len);
-	if (!handle || len < sizeof(handle))
-		return -ENODEV;
-	codec_node = of_find_node_by_phandle(*handle);
+	if (handle && len >= sizeof(handle))
+		codec_node = of_find_node_by_phandle(*handle);
+	else {
+		/* Check for the codec child nodes */
+		for_each_child_of_node(node, codec_node) {
+			struct platform_device *pdev;
+			struct dev_archdata dev_ad = {};
+			char name[MODULE_NAME_LEN];
+			const u32 *addr;
+			int len;
+
+			if (of_modalias_node(codec_node, name, sizeof(name)) < 0)
+				continue;
+
+			addr = of_get_property(codec_node, "reg", &len);
+			if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
+				pr_err("invalid codec reg in device tree\n");
+				continue;
+			}
+			request_module("%s", name);
+
+			pdev = platform_device_alloc(name, 0);
+
+			dev_archdata_set_node(&dev_ad, codec_node);
+			pdev->dev.archdata = dev_ad;
+
+			rc = platform_device_add(pdev);
+			if (rc) {
+				platform_device_put(pdev);
+				return rc;
+			}
+			break;
+		}
+	}
 	if (!codec_node)
 		return -ENODEV;
 	pr_info("looking for codec: %s\n", codec_node->full_name);
@@ -156,10 +199,12 @@ int of_snd_soc_register_platform(struct snd_soc_platform *platform,
 		goto out;
 	}
 
-	of_soc->platform_node = node;
-	of_soc->dai_link.cpu_dai = cpu_dai;
-	of_soc->card.platform = platform;
-	of_soc->card.name = of_soc->dai_link.cpu_dai->name;
+	of_soc->cpu_dai_node = node;
+	of_soc->card.num_links = min(count, of_soc->card.num_links);
+	for (i = 0; i < of_soc->card.num_links; i++) {
+		of_soc->dai_link[i].stream_name = cpu_dai[i].name;
+		of_soc->dai_link[i].cpu_dai = &cpu_dai[i];
+	}
 
 	/* Now try to register the SoC device */
 	of_snd_soc_register_device(of_soc);
@@ -168,4 +213,65 @@ int of_snd_soc_register_platform(struct snd_soc_platform *platform,
 	mutex_unlock(&of_snd_soc_mutex);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(of_snd_soc_register_cpu_dai);
+
+int of_snd_soc_register_platform(struct snd_soc_platform *platform)
+{
+	struct of_snd_soc_device *of_soc;
+	int rc = 0;
+
+	pr_info("registering ASoC platform driver: %s\n", platform->name);
+	template_platform = platform;
+
+	mutex_lock(&of_snd_soc_mutex);
+	list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
+		of_soc->card.platform = platform;
+		of_snd_soc_register_device(of_soc);
+	}
+	mutex_unlock(&of_snd_soc_mutex);
+	return rc;
+}
 EXPORT_SYMBOL_GPL(of_snd_soc_register_platform);
+
+int of_snd_soc_register_fabric(const char *name, struct snd_soc_ops *ops,
+								int (*init)(struct snd_soc_codec *codec))
+{
+	int i;
+	struct of_snd_soc_device *of_soc;
+
+	pr_info("registering ASoC fabric driver: %s\n", name);
+	template_name = name;
+	template_ops = ops;
+	template_init = init;
+
+	mutex_lock(&of_snd_soc_mutex);
+	list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
+		for (i = 0; i < SOC_OF_SIMPLE_MAX_DAI; i++) {
+			of_soc->dai_link[i].ops = ops;
+			of_soc->dai_link[i].init = init;
+		}
+		of_soc->card.name = (char *)name;
+		of_snd_soc_register_device(of_soc);
+	}
+	mutex_unlock(&of_snd_soc_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_snd_soc_register_fabric);
+
+/* If no board specific fabric driver has been registered, register a default one */
+int of_snd_soc_register_default_fabric(void)
+{
+	struct device_node *root;
+	const char *model = "";
+
+	if (template_name != NULL)
+		return 0;
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = of_get_property(root, "model", NULL);
+
+	return of_snd_soc_register_fabric(model, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(of_snd_soc_register_default_fabric);
+

  parent reply	other threads:[~2009-05-14  1:59 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-14  1:58 [PATCH V1 00/13] mpc5200 audio rework for AC97 Jon Smirl
2009-05-14  1:59 ` [PATCH V1 01/13] Temporarily undo 2008f137e92220b98120c4803499cdddb2b0fb06 Jon Smirl
2009-05-14 10:13   ` Mark Brown
2009-05-14 14:37     ` Jon Smirl
2009-05-14 16:25       ` Mark Brown
2009-05-14 20:21         ` Jon Smirl
2009-05-14  1:59 ` [PATCH V1 02/13] Basic split of mpc5200 DMA code out from mpc5200_psc_i2s Jon Smirl
2009-05-14  1:59 ` [PATCH V1 03/13] Rename the PSC functions to DMA Jon Smirl
2009-05-14 10:14   ` Mark Brown
2009-05-14  1:59 ` [PATCH V1 04/13] redo 2008f137e92220b98120c4803499cdddb2b0fb06 Jon Smirl
2009-05-14  1:59 ` [PATCH V1 05/13] Add a few more mpc5200 PSC defines Jon Smirl
2009-05-14 10:15   ` Mark Brown
2009-05-14  1:59 ` Jon Smirl [this message]
2009-05-14 10:41   ` [PATCH V1 06/13] Allow a custom ASOC fabric driver with soc-of-simple Mark Brown
2009-05-14  1:59 ` [PATCH V1 07/13] Add SNDRV_PCM_FMTBIT_S32_BE as a valid AC97 format Jon Smirl
2009-05-14 11:53   ` Mark Brown
2009-05-14  1:59 ` [PATCH V1 08/13] Have the WM9712 driver self register itself Jon Smirl
2009-05-14 10:45   ` Mark Brown
2009-05-14  1:59 ` [PATCH V1 09/13] Main rewite of the mpc5200 audio DMA code Jon Smirl
2009-05-14 10:51   ` Mark Brown
2009-05-14 14:50     ` Jon Smirl
2009-05-14 19:14       ` Mark Brown
2009-05-14  1:59 ` [PATCH V1 10/13] Codec for STAC9766 used on the Efika Jon Smirl
2009-05-14 11:03   ` Mark Brown
2009-05-14  1:59 ` [PATCH V1 11/13] AC97 driver for mpc5200 Jon Smirl
2009-05-14  2:17   ` Jon Smirl
2009-05-14 11:39   ` Mark Brown
2009-05-14  1:59 ` [PATCH V1 12/13] Fabric bindings for STAC9766 on the Efika Jon Smirl
2009-05-14  1:59 ` [PATCH V1 13/13] Support for AC97 on Phytec pmc030 base board Jon Smirl
2009-05-14  2:03 ` [PATCH V1 00/13] mpc5200 audio rework for AC97 Jon Smirl
2009-05-14  3:34 ` Grant Likely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090514015912.28145.22291.stgit@terra \
    --to=jonsmirl@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@sirena.org.uk \
    --cc=grant.likely@secretlab.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.