2 * OF helpers for ALSA SoC Layer
4 * Copyright (C) 2008, Secret Lab Technologies Ltd.
7 #include <linux/module.h>
8 #include <linux/moduleparam.h>
9 #include <linux/init.h>
10 #include <linux/delay.h>
12 #include <linux/bitops.h>
13 #include <linux/platform_device.h>
15 #include <linux/slab.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 #include <sound/soc-of-simple.h>
21 #include <sound/initval.h>
23 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
24 MODULE_LICENSE("GPL");
25 MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings");
27 static DEFINE_MUTEX(of_snd_soc_mutex
);
28 static LIST_HEAD(of_snd_soc_device_list
);
29 static int of_snd_soc_next_index
;
31 struct of_snd_soc_device
{
33 struct list_head list
;
34 struct snd_soc_device device
;
35 struct snd_soc_card card
;
36 struct snd_soc_dai_link dai_link
;
37 struct platform_device
*pdev
;
38 struct device_node
*platform_node
;
39 struct device_node
*codec_node
;
42 static struct snd_soc_ops of_snd_soc_ops
= {
45 static struct of_snd_soc_device
*
46 of_snd_soc_get_device(struct device_node
*codec_node
)
48 struct of_snd_soc_device
*of_soc
;
50 list_for_each_entry(of_soc
, &of_snd_soc_device_list
, list
) {
51 if (of_soc
->codec_node
== codec_node
)
55 of_soc
= kzalloc(sizeof(struct of_snd_soc_device
), GFP_KERNEL
);
59 /* Initialize the structure and add it to the global list */
60 of_soc
->codec_node
= codec_node
;
61 of_soc
->id
= of_snd_soc_next_index
++;
62 of_soc
->card
.dai_link
= &of_soc
->dai_link
;
63 of_soc
->card
.num_links
= 1;
64 of_soc
->device
.card
= &of_soc
->card
;
65 of_soc
->dai_link
.ops
= &of_snd_soc_ops
;
66 list_add(&of_soc
->list
, &of_snd_soc_device_list
);
71 static void of_snd_soc_register_device(struct of_snd_soc_device
*of_soc
)
73 struct platform_device
*pdev
;
76 /* Only register the device if both the codec and platform have
78 if ((!of_soc
->device
.codec_data
) || (!of_soc
->platform_node
))
81 pr_info("platform<-->codec match achieved; registering machine\n");
83 pdev
= platform_device_alloc("soc-audio", of_soc
->id
);
85 pr_err("of_soc: platform_device_alloc() failed\n");
89 pdev
->dev
.platform_data
= of_soc
;
90 platform_set_drvdata(pdev
, &of_soc
->device
);
91 of_soc
->device
.dev
= &pdev
->dev
;
93 /* The ASoC device is complete; register it */
94 rc
= platform_device_add(pdev
);
96 pr_err("of_soc: platform_device_add() failed\n");
102 int of_snd_soc_register_codec(struct snd_soc_codec_device
*codec_dev
,
103 void *codec_data
, struct snd_soc_dai
*dai
,
104 struct device_node
*node
)
106 struct of_snd_soc_device
*of_soc
;
109 pr_info("registering ASoC codec driver: %s\n", node
->full_name
);
111 mutex_lock(&of_snd_soc_mutex
);
112 of_soc
= of_snd_soc_get_device(node
);
118 /* Store the codec data */
119 of_soc
->device
.codec_data
= codec_data
;
120 of_soc
->device
.codec_dev
= codec_dev
;
121 of_soc
->dai_link
.name
= (char *)node
->name
;
122 of_soc
->dai_link
.stream_name
= (char *)node
->name
;
123 of_soc
->dai_link
.codec_dai
= dai
;
125 /* Now try to register the SoC device */
126 of_snd_soc_register_device(of_soc
);
129 mutex_unlock(&of_snd_soc_mutex
);
132 EXPORT_SYMBOL_GPL(of_snd_soc_register_codec
);
134 int of_snd_soc_register_platform(struct snd_soc_platform
*platform
,
135 struct device_node
*node
,
136 struct snd_soc_dai
*cpu_dai
)
138 struct of_snd_soc_device
*of_soc
;
139 struct device_node
*codec_node
;
140 const phandle
*handle
;
143 pr_info("registering ASoC platform driver: %s\n", node
->full_name
);
145 handle
= of_get_property(node
, "codec-handle", &len
);
146 if (!handle
|| len
< sizeof(handle
))
148 codec_node
= of_find_node_by_phandle(*handle
);
151 pr_info("looking for codec: %s\n", codec_node
->full_name
);
153 mutex_lock(&of_snd_soc_mutex
);
154 of_soc
= of_snd_soc_get_device(codec_node
);
160 of_soc
->platform_node
= node
;
161 of_soc
->dai_link
.cpu_dai
= cpu_dai
;
162 of_soc
->card
.platform
= platform
;
163 of_soc
->card
.name
= of_soc
->dai_link
.cpu_dai
->name
;
165 /* Now try to register the SoC device */
166 of_snd_soc_register_device(of_soc
);
169 mutex_unlock(&of_snd_soc_mutex
);
172 EXPORT_SYMBOL_GPL(of_snd_soc_register_platform
);