diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2012-09-10 06:46:25 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-18 09:45:05 -0400 |
commit | 019a7e6b7b312b17cd74b45d09d4ec17486c4088 (patch) | |
tree | 57fa578d2bae3b906b7082804f008406be41a056 /drivers/mfd | |
parent | 1cc44f4354c03d1ebcfa670875478ee1c9368086 (diff) |
mfd: twl4030-audio: Add DT support
Support for loading the twl4030 audio module via devicetree.
Sub devices for codec and vibra will be created as mfd devices once the
core MFD driver is loaded when the kernel is booted with a DT blob.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/twl4030-audio.c | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index 31605fa02ca1..5c11acf9e0fd 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/of.h> | ||
32 | #include <linux/of_platform.h> | ||
31 | #include <linux/i2c/twl.h> | 33 | #include <linux/i2c/twl.h> |
32 | #include <linux/mfd/core.h> | 34 | #include <linux/mfd/core.h> |
33 | #include <linux/mfd/twl4030-audio.h> | 35 | #include <linux/mfd/twl4030-audio.h> |
@@ -156,15 +158,42 @@ unsigned int twl4030_audio_get_mclk(void) | |||
156 | } | 158 | } |
157 | EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk); | 159 | EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk); |
158 | 160 | ||
161 | static bool twl4030_audio_has_codec(struct twl4030_audio_data *pdata, | ||
162 | struct device_node *node) | ||
163 | { | ||
164 | if (pdata && pdata->codec) | ||
165 | return true; | ||
166 | |||
167 | if (of_find_node_by_name(node, "codec")) | ||
168 | return true; | ||
169 | |||
170 | return false; | ||
171 | } | ||
172 | |||
173 | static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata, | ||
174 | struct device_node *node) | ||
175 | { | ||
176 | int vibra; | ||
177 | |||
178 | if (pdata && pdata->vibra) | ||
179 | return true; | ||
180 | |||
181 | if (!of_property_read_u32(node, "ti,enable-vibra", &vibra) && vibra) | ||
182 | return true; | ||
183 | |||
184 | return false; | ||
185 | } | ||
186 | |||
159 | static int __devinit twl4030_audio_probe(struct platform_device *pdev) | 187 | static int __devinit twl4030_audio_probe(struct platform_device *pdev) |
160 | { | 188 | { |
161 | struct twl4030_audio *audio; | 189 | struct twl4030_audio *audio; |
162 | struct twl4030_audio_data *pdata = pdev->dev.platform_data; | 190 | struct twl4030_audio_data *pdata = pdev->dev.platform_data; |
191 | struct device_node *node = pdev->dev.of_node; | ||
163 | struct mfd_cell *cell = NULL; | 192 | struct mfd_cell *cell = NULL; |
164 | int ret, childs = 0; | 193 | int ret, childs = 0; |
165 | u8 val; | 194 | u8 val; |
166 | 195 | ||
167 | if (!pdata) { | 196 | if (!pdata && !node) { |
168 | dev_err(&pdev->dev, "Platform data is missing\n"); | 197 | dev_err(&pdev->dev, "Platform data is missing\n"); |
169 | return -EINVAL; | 198 | return -EINVAL; |
170 | } | 199 | } |
@@ -202,18 +231,22 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev) | |||
202 | audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL; | 231 | audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL; |
203 | audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN; | 232 | audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN; |
204 | 233 | ||
205 | if (pdata->codec) { | 234 | if (twl4030_audio_has_codec(pdata, node)) { |
206 | cell = &audio->cells[childs]; | 235 | cell = &audio->cells[childs]; |
207 | cell->name = "twl4030-codec"; | 236 | cell->name = "twl4030-codec"; |
208 | cell->platform_data = pdata->codec; | 237 | if (pdata) { |
209 | cell->pdata_size = sizeof(*pdata->codec); | 238 | cell->platform_data = pdata->codec; |
239 | cell->pdata_size = sizeof(*pdata->codec); | ||
240 | } | ||
210 | childs++; | 241 | childs++; |
211 | } | 242 | } |
212 | if (pdata->vibra) { | 243 | if (twl4030_audio_has_vibra(pdata, node)) { |
213 | cell = &audio->cells[childs]; | 244 | cell = &audio->cells[childs]; |
214 | cell->name = "twl4030-vibra"; | 245 | cell->name = "twl4030-vibra"; |
215 | cell->platform_data = pdata->vibra; | 246 | if (pdata) { |
216 | cell->pdata_size = sizeof(*pdata->vibra); | 247 | cell->platform_data = pdata->vibra; |
248 | cell->pdata_size = sizeof(*pdata->vibra); | ||
249 | } | ||
217 | childs++; | 250 | childs++; |
218 | } | 251 | } |
219 | 252 | ||
@@ -245,10 +278,17 @@ static int __devexit twl4030_audio_remove(struct platform_device *pdev) | |||
245 | return 0; | 278 | return 0; |
246 | } | 279 | } |
247 | 280 | ||
281 | static const struct of_device_id twl4030_audio_of_match[] = { | ||
282 | {.compatible = "ti,twl4030-audio", }, | ||
283 | { }, | ||
284 | }; | ||
285 | MODULE_DEVICE_TABLE(of, twl4030_audio_of_match); | ||
286 | |||
248 | static struct platform_driver twl4030_audio_driver = { | 287 | static struct platform_driver twl4030_audio_driver = { |
249 | .driver = { | 288 | .driver = { |
250 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
251 | .name = "twl4030-audio", | 290 | .name = "twl4030-audio", |
291 | .of_match_table = twl4030_audio_of_match, | ||
252 | }, | 292 | }, |
253 | .probe = twl4030_audio_probe, | 293 | .probe = twl4030_audio_probe, |
254 | .remove = __devexit_p(twl4030_audio_remove), | 294 | .remove = __devexit_p(twl4030_audio_remove), |