aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl/soc-of-simple.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2008-07-29 06:42:28 -0400
committerJaroslav Kysela <perex@perex.cz>2008-07-29 15:32:20 -0400
commit84bc278b1f04920e867e4b46e094bcc066393d41 (patch)
tree3c4dfdabeee65ebe0b781f14b7df3d82c0444eaf /sound/soc/fsl/soc-of-simple.c
parentf8ba0b7bfd06a2a5b3c49ff8d71cad31f57b0d51 (diff)
ALSA: ASoC: Add OpenFirmware helper for matching bus and codec drivers
Simple utility layer for creating ASoC machine instances based on data in the OpenFirmware device tree. OF aware platform drivers and codec drivers register themselves with this framework and the framework automatically instantiates a machine driver. At the moment, the driver is not very capable and it is expected to be extended as more features are needed for specifying the configuration in the device tree. This is most likely temporary glue code to work around limitations in the ASoC v1 framework. When v2 is merged, most of this driver will need to be reworked. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/soc/fsl/soc-of-simple.c')
-rw-r--r--sound/soc/fsl/soc-of-simple.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
new file mode 100644
index 000000000000..0382fdac51cd
--- /dev/null
+++ b/sound/soc/fsl/soc-of-simple.c
@@ -0,0 +1,171 @@
1/*
2 * OF helpers for ALSA SoC Layer
3 *
4 * Copyright (C) 2008, Secret Lab Technologies Ltd.
5 */
6
7#include <linux/module.h>
8#include <linux/moduleparam.h>
9#include <linux/init.h>
10#include <linux/delay.h>
11#include <linux/pm.h>
12#include <linux/bitops.h>
13#include <linux/platform_device.h>
14#include <linux/of.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/soc-of-simple.h>
20#include <sound/initval.h>
21
22MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
23MODULE_LICENSE("GPL");
24MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings");
25
26static DEFINE_MUTEX(of_snd_soc_mutex);
27static LIST_HEAD(of_snd_soc_device_list);
28static int of_snd_soc_next_index;
29
30struct of_snd_soc_device {
31 int id;
32 struct list_head list;
33 struct snd_soc_device device;
34 struct snd_soc_machine machine;
35 struct snd_soc_dai_link dai_link;
36 struct platform_device *pdev;
37 struct device_node *platform_node;
38 struct device_node *codec_node;
39};
40
41static struct snd_soc_ops of_snd_soc_ops = {
42};
43
44static struct of_snd_soc_device *
45of_snd_soc_get_device(struct device_node *codec_node)
46{
47 struct of_snd_soc_device *of_soc;
48
49 list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
50 if (of_soc->codec_node == codec_node)
51 return of_soc;
52 }
53
54 of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL);
55 if (!of_soc)
56 return NULL;
57
58 /* Initialize the structure and add it to the global list */
59 of_soc->codec_node = codec_node;
60 of_soc->id = of_snd_soc_next_index++;
61 of_soc->machine.dai_link = &of_soc->dai_link;
62 of_soc->machine.num_links = 1;
63 of_soc->device.machine = &of_soc->machine;
64 of_soc->dai_link.ops = &of_snd_soc_ops;
65 list_add(&of_soc->list, &of_snd_soc_device_list);
66
67 return of_soc;
68}
69
70static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc)
71{
72 struct platform_device *pdev;
73 int rc;
74
75 /* Only register the device if both the codec and platform have
76 * been registered */
77 if ((!of_soc->device.codec_data) || (!of_soc->platform_node))
78 return;
79
80 pr_info("platform<-->codec match achieved; registering machine\n");
81
82 pdev = platform_device_alloc("soc-audio", of_soc->id);
83 if (!pdev) {
84 pr_err("of_soc: platform_device_alloc() failed\n");
85 return;
86 }
87
88 pdev->dev.platform_data = of_soc;
89 platform_set_drvdata(pdev, &of_soc->device);
90 of_soc->device.dev = &pdev->dev;
91
92 /* The ASoC device is complete; register it */
93 rc = platform_device_add(pdev);
94 if (rc) {
95 pr_err("of_soc: platform_device_add() failed\n");
96 return;
97 }
98
99}
100
101int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
102 void *codec_data, struct snd_soc_dai *dai,
103 struct device_node *node)
104{
105 struct of_snd_soc_device *of_soc;
106 int rc = 0;
107
108 pr_info("registering ASoC codec driver: %s\n", node->full_name);
109
110 mutex_lock(&of_snd_soc_mutex);
111 of_soc = of_snd_soc_get_device(node);
112 if (!of_soc) {
113 rc = -ENOMEM;
114 goto out;
115 }
116
117 /* Store the codec data */
118 of_soc->device.codec_data = codec_data;
119 of_soc->device.codec_dev = codec_dev;
120 of_soc->dai_link.name = (char *)node->name;
121 of_soc->dai_link.stream_name = (char *)node->name;
122 of_soc->dai_link.codec_dai = dai;
123
124 /* Now try to register the SoC device */
125 of_snd_soc_register_device(of_soc);
126
127 out:
128 mutex_unlock(&of_snd_soc_mutex);
129 return rc;
130}
131EXPORT_SYMBOL_GPL(of_snd_soc_register_codec);
132
133int of_snd_soc_register_platform(struct snd_soc_platform *platform,
134 struct device_node *node,
135 struct snd_soc_dai *cpu_dai)
136{
137 struct of_snd_soc_device *of_soc;
138 struct device_node *codec_node;
139 const phandle *handle;
140 int len, rc = 0;
141
142 pr_info("registering ASoC platform driver: %s\n", node->full_name);
143
144 handle = of_get_property(node, "codec-handle", &len);
145 if (!handle || len < sizeof(handle))
146 return -ENODEV;
147 codec_node = of_find_node_by_phandle(*handle);
148 if (!codec_node)
149 return -ENODEV;
150 pr_info("looking for codec: %s\n", codec_node->full_name);
151
152 mutex_lock(&of_snd_soc_mutex);
153 of_soc = of_snd_soc_get_device(codec_node);
154 if (!of_soc) {
155 rc = -ENOMEM;
156 goto out;
157 }
158
159 of_soc->platform_node = node;
160 of_soc->dai_link.cpu_dai = cpu_dai;
161 of_soc->device.platform = platform;
162 of_soc->machine.name = of_soc->dai_link.cpu_dai->name;
163
164 /* Now try to register the SoC device */
165 of_snd_soc_register_device(of_soc);
166
167 out:
168 mutex_unlock(&of_snd_soc_mutex);
169 return rc;
170}
171EXPORT_SYMBOL_GPL(of_snd_soc_register_platform);