diff options
Diffstat (limited to 'sound/soc/omap')
| -rw-r--r-- | sound/soc/omap/omap3h1.c | 157 |
1 files changed, 130 insertions, 27 deletions
diff --git a/sound/soc/omap/omap3h1.c b/sound/soc/omap/omap3h1.c index 108d104502d..f61949b295e 100644 --- a/sound/soc/omap/omap3h1.c +++ b/sound/soc/omap/omap3h1.c @@ -24,8 +24,11 @@ #define DEBUG #include <linux/clk.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/platform_device.h> #include <linux/module.h> +#include <linux/of.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> @@ -35,6 +38,10 @@ #include "omap-mcbsp.h" +static struct clk *per_96m_fck; +static unsigned long rate; +static int mic_gpio_enable; + static int omap3h1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -46,16 +53,18 @@ static int omap3h1_hw_params(struct snd_pcm_substream *substream, //freq = 256 * params_rate(params); // We are triggering from the 96 MHz FSCK - pr_info("ASoc OMAP3H1: setting according to system clock\n"); + + // pr_info("ASoc OMAP3H1: setting system clock to: %d", freq); ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK, - 96000000, SND_SOC_CLOCK_OUT); + rate, SND_SOC_CLOCK_OUT); if (ret < 0) { printk(KERN_ERR "can't set DMIC cpu system clock\n"); return ret; } - // Set the divider so that our clock rate is ~3KHz, this is about 48KHz sampling frequency on the mic - // (32-bit/channel, 2 channels, 48 Khz sampling) + // Set the divider so that our clock rate is ~3KHz, this is about + // 48KHz sampling frequency on the mic (32-bit/channel, 2 channels, 48 + // Khz sampling) ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 32); if (ret < 0) { pr_err("ASoc OMAP3H1: can't set SRG clock divider\n"); @@ -65,8 +74,22 @@ static int omap3h1_hw_params(struct snd_pcm_substream *substream, return 0; } +static int omap3h1_startup(struct snd_pcm_substream *substream) +{ + gpio_set_value(mic_gpio_enable, 1); + return clk_enable(per_96m_fck); +} + +static void omap3h1_shutdown(struct snd_pcm_substream *substream) +{ + gpio_set_value(mic_gpio_enable, 0); + clk_disable(per_96m_fck); +} + static struct snd_soc_ops omap3h1_ops = { .hw_params = omap3h1_hw_params, + .startup = omap3h1_startup, + .shutdown = omap3h1_shutdown, }; //static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = { @@ -103,45 +126,125 @@ static struct snd_soc_card snd_soc_omap3h1 = { // .num_dapm_routes = ARRAY_SIZE(dmic_audio_map), }; -static struct platform_device *omap3h1_snd_device; - -static int __init omap3h1_soc_init(void) +static int omap3h1_card_probe(struct platform_device *pdev) { - int ret; + struct device_node *node = pdev->dev.of_node; + struct snd_soc_card *card = &snd_soc_omap3h1; + int ret = 0; + int gpio; + +#ifdef CONFIG_OF + if (node) { + struct device_node *dai_node; - if (!(machine_is_omap3_h1())) + dai_node = of_parse_phandle(node, "olio,mcbsp", 0); + if (!dai_node) { + dev_err(&pdev->dev, "mcbsp node is not provided\n"); + return -EINVAL; + } + omap3h1_dai.cpu_dai_name = NULL; + omap3h1_dai.cpu_of_node = dai_node; + + } else { + dev_err(&pdev->dev, "Missing node\n"); return -ENODEV; - pr_info("OMAP3 H1 SoC init\n"); + } - omap3h1_snd_device = platform_device_alloc("soc-audio", -1); - if (!omap3h1_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; + gpio = of_get_named_gpio(node, "olio,mic_enable", 0); + ret = (gpio < 0) ? -ENODEV : gpio_request(gpio, "mic_enable"); + if (ret) { + dev_err(&pdev->dev, "GPIO request error gpio=%d err=%d\n", gpio, ret); + return ret; } + gpio_direction_output(gpio, 0); + mic_gpio_enable = gpio; - platform_set_drvdata(omap3h1_snd_device, &snd_soc_omap3h1); +#endif - ret = platform_device_add(omap3h1_snd_device); - if (ret) - goto err1; + card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, NULL); - return 0; + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + return ret; + } -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(omap3h1_snd_device); + per_96m_fck = clk_get(&pdev->dev, "per_96m_fck"); + if (IS_ERR(per_96m_fck)) { + dev_err(&pdev->dev, "could not get per_96m_fck clock\n"); + return PTR_ERR(per_96m_fck); + } + + rate = clk_get_rate(per_96m_fck); - return ret; + return 0; } -static void __exit omap3h1_soc_exit(void) +static int omap3h1_card_remove(struct platform_device *pdev) { - platform_device_unregister(omap3h1_snd_device); + struct snd_soc_card *card = platform_get_drvdata(pdev); + gpio_free(mic_gpio_enable); + snd_soc_unregister_card(card); + + return 0; } -module_init(omap3h1_soc_init); -module_exit(omap3h1_soc_exit); +/** + * omap3h1_sound_suspend - suspend microphone + * + */ + +static int omap3h1_sound_suspend(struct device *dev) { + printk ("OLIO %s:%s Suspending\n", __FILE__, __FUNCTION__); + + snd_soc_suspend(dev); + + return 0; +} + + +/** + * omap3h1_sound_resume - resume microphone + * + */ + +static int omap3h1_sound_resume(struct device *dev) { + printk ("OLIO %s:%s Resuming\n", __FILE__, __FUNCTION__); + + snd_soc_resume (dev); + + return 0; +} + + +/* ---------------------------------------------------------------------- */ + +static const struct dev_pm_ops omap3h1_sound_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(omap3h1_sound_suspend, omap3h1_sound_resume) +}; + + +static const struct of_device_id omap_soc_h1_of_match[] = { + {.compatible = "olio,omap-soc-omap3h1", }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_soc_h1_of_match); + +static struct platform_driver omap3h1_driver = { + .driver = { + .name = "omap-soc-omap3h1", + .of_match_table = of_match_ptr(omap_soc_h1_of_match), + .pm = &snd_soc_pm_ops, + }, + .probe = omap3h1_card_probe, + .remove = omap3h1_card_remove, +}; + +module_platform_driver(omap3h1_driver); MODULE_AUTHOR("Evan Wilson <evan@oliodevices.com"); MODULE_DESCRIPTION("ALSA SoC OMAP3 H1"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:omap-soc-omap3h1"); |