diff options
Diffstat (limited to 'sound/soc/atmel/sam9g20_wm8731.c')
| -rw-r--r-- | sound/soc/atmel/sam9g20_wm8731.c | 131 |
1 files changed, 88 insertions, 43 deletions
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index c88351488f4..bb1149126c5 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -37,6 +37,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/i2c.h> +#include <linux/of.h> #include <linux/atmel-ssc.h> @@ -47,7 +48,6 @@ #include <asm/mach-types.h> #include <mach/hardware.h> -#include <mach/gpio.h> #include "../codecs/wm8731.h" #include "atmel-pcm.h" @@ -154,35 +154,24 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) return ret; } - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets, - ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); - /* Set up specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - /* not connected */ snd_soc_dapm_nc_pin(dapm, "RLINEIN"); snd_soc_dapm_nc_pin(dapm, "LLINEIN"); -#ifdef ENABLE_MIC_INPUT - snd_soc_dapm_enable_pin(dapm, "Int Mic"); -#else - snd_soc_dapm_nc_pin(dapm, "Int Mic"); +#ifndef ENABLE_MIC_INPUT + snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic"); #endif - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - return 0; } static struct snd_soc_dai_link at91sam9g20ek_dai = { .name = "WM8731", .stream_name = "WM8731 PCM", - .cpu_dai_name = "atmel-ssc-dai.0", + .cpu_dai_name = "at91rm9200_ssc.0", .codec_dai_name = "wm8731-hifi", .init = at91sam9g20ek_wm8731_init, - .platform_name = "atmel-pcm-audio", + .platform_name = "at91rm9200_ssc.0", .codec_name = "wm8731.0-001b", .ops = &at91sam9g20ek_ops, }; @@ -193,22 +182,31 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = { .dai_link = &at91sam9g20ek_dai, .num_links = 1, .set_bias_level = at91sam9g20ek_set_bias_level, -}; -static struct platform_device *at91sam9g20ek_snd_device; + .dapm_widgets = at91sam9g20ek_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), +}; -static int __init at91sam9g20ek_init(void) +static int at91sam9g20ek_audio_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; + struct device_node *codec_np, *cpu_np; struct clk *pllb; + struct snd_soc_card *card = &snd_soc_at91sam9g20ek; int ret; - if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc())) - return -ENODEV; + if (!np) { + if (!(machine_is_at91sam9g20ek() || + machine_is_at91sam9g20ek_2mmc())) + return -ENODEV; + } ret = atmel_ssc_set_audio(0); - if (ret != 0) { - pr_err("Failed to set SSC 0 for audio: %d\n", ret); - return ret; + if (ret) { + dev_err(&pdev->dev, "ssc channel is not valid\n"); + return -EINVAL; } /* @@ -236,45 +234,92 @@ static int __init at91sam9g20ek_init(void) clk_set_rate(mclk, MCLK_RATE); - at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); - if (!at91sam9g20ek_snd_device) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - ret = -ENOMEM; - goto err_mclk; + card->dev = &pdev->dev; + + /* Parse device node info */ + if (np) { + ret = snd_soc_of_parse_card_name(card, "atmel,model"); + if (ret) + goto err; + + ret = snd_soc_of_parse_audio_routing(card, + "atmel,audio-routing"); + if (ret) + goto err; + + /* Parse codec info */ + at91sam9g20ek_dai.codec_name = NULL; + codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); + if (!codec_np) { + dev_err(&pdev->dev, "codec info missing\n"); + return -EINVAL; + } + at91sam9g20ek_dai.codec_of_node = codec_np; + + /* Parse dai and platform info */ + at91sam9g20ek_dai.cpu_dai_name = NULL; + at91sam9g20ek_dai.platform_name = NULL; + cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); + if (!cpu_np) { + dev_err(&pdev->dev, "dai and pcm info missing\n"); + return -EINVAL; + } + at91sam9g20ek_dai.cpu_of_node = cpu_np; + at91sam9g20ek_dai.platform_of_node = cpu_np; + + of_node_put(codec_np); + of_node_put(cpu_np); } - platform_set_drvdata(at91sam9g20ek_snd_device, - &snd_soc_at91sam9g20ek); - - ret = platform_device_add(at91sam9g20ek_snd_device); + ret = snd_soc_register_card(card); if (ret) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - goto err_device_add; + printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n"); } return ret; -err_device_add: - platform_device_put(at91sam9g20ek_snd_device); err_mclk: clk_put(mclk); mclk = NULL; err: + atmel_ssc_put_audio(0); return ret; } -static void __exit at91sam9g20ek_exit(void) +static int at91sam9g20ek_audio_remove(struct platform_device *pdev) { - platform_device_unregister(at91sam9g20ek_snd_device); - at91sam9g20ek_snd_device = NULL; - clk_put(mclk); + struct snd_soc_card *card = platform_get_drvdata(pdev); + + clk_disable(mclk); mclk = NULL; + snd_soc_unregister_card(card); + atmel_ssc_put_audio(0); + + return 0; } -module_init(at91sam9g20ek_init); -module_exit(at91sam9g20ek_exit); +#ifdef CONFIG_OF +static const struct of_device_id at91sam9g20ek_wm8731_dt_ids[] = { + { .compatible = "atmel,at91sam9g20ek-wm8731-audio", }, + { } +}; +MODULE_DEVICE_TABLE(of, at91sam9g20ek_wm8731_dt_ids); +#endif + +static struct platform_driver at91sam9g20ek_audio_driver = { + .driver = { + .name = "at91sam9g20ek-audio", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids), + }, + .probe = at91sam9g20ek_audio_probe, + .remove = at91sam9g20ek_audio_remove, +}; + +module_platform_driver(at91sam9g20ek_audio_driver); /* Module information */ MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731"); +MODULE_ALIAS("platform:at91sam9g20ek-audio"); MODULE_LICENSE("GPL"); |
