diff options
Diffstat (limited to 'sound/soc/omap')
| -rw-r--r-- | sound/soc/omap/Kconfig | 1 | ||||
| -rw-r--r-- | sound/soc/omap/omap3h1.c | 197 |
2 files changed, 115 insertions, 83 deletions
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 66d98e26a24..08c94b19bb9 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -31,6 +31,7 @@ config SND_OMAP_SOC_OMAP3_H1 depends on SND_OMAP_SOC && MACH_OMAP3_H1 select SND_OMAP_SOC_MCBSP select SND_SOC_DMIC + select SND_SOC_OMAP3H1_BT_SCO help Say Y if you want to add support for SoC audio on the Olio H1 board. diff --git a/sound/soc/omap/omap3h1.c b/sound/soc/omap/omap3h1.c index f61949b295e..faad74810c3 100644 --- a/sound/soc/omap/omap3h1.c +++ b/sound/soc/omap/omap3h1.c @@ -22,7 +22,7 @@ * */ -#define DEBUG +//#define DEBUG #include <linux/clk.h> #include <linux/gpio.h> #include <linux/of_gpio.h> @@ -42,19 +42,22 @@ 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, +static int omap3h1_hw_in_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - //unsigned int fmt; int ret = 0; - unsigned int freq; - //freq = 256 * params_rate(params); - // We are triggering from the 96 MHz FSCK + pr_info("ASoc OMAP3H1: omap3h1_hw_in_params\n"); + pr_info("ASoc OMAP3H1: in params channels=%d\n", params_channels(params)); + pr_info("ASoc OMAP3H1: in params rate=%d\n", params_rate(params)); + pr_info("ASoc OMAP3H1: in params params_period_size=%d\n", params_period_size(params)); + pr_info("ASoc OMAP3H1: in params params_periods=%d\n", params_periods(params)); + pr_info("ASoc OMAP3H1: in params params_buffer_size=%d\n", params_buffer_size(params)); + pr_info("ASoc OMAP3H1: in params params_buffer_bytes=%d\n", params_buffer_bytes(params)); - // pr_info("ASoc OMAP3H1: setting system clock to: %d", freq); + /* Set McBSP clock to use PER_96M_FCLK */ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK, rate, SND_SOC_CLOCK_OUT); if (ret < 0) { @@ -62,68 +65,121 @@ static int omap3h1_hw_params(struct snd_pcm_substream *substream, 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) + /* The microphone becomes operational 2^18 clock cycles */ + /* (85 ms with SCK at 3.072 MHz) */ 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"); + pr_err("ASoc OMAP3H1: can't set MIC clock divider\n"); return ret; } return 0; } -static int omap3h1_startup(struct snd_pcm_substream *substream) +static int omap3h1_hw_out_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = 0; + + pr_info("ASoc OMAP3H1: omap3h1_hw_out_params"); + pr_info("ASoc OMAP3H1: out params channels=%u\n", params_channels(params)); + pr_info("ASoc OMAP3H1: out params rate=%u\n", params_rate(params)); + pr_info("ASoc OMAP3H1: out params params_period_size=%u\n", params_period_size(params)); + pr_info("ASoc OMAP3H1: out params params_periods=%u\n", params_periods(params)); + pr_info("ASoc OMAP3H1: out params params_buffer_size=%u\n", params_buffer_size(params)); + pr_info("ASoc OMAP3H1: out params params_buffer_bytes=%u\n", params_buffer_bytes(params)); + + /* Set McBSP clock to use PER_96M_FCLK */ + ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK, + rate, SND_SOC_CLOCK_OUT); + if (ret < 0) { + printk(KERN_ERR "can't set DMIC cpu system clock\n"); + return ret; + } + + /* The BT operates on 512K freq */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, rate/512000); + if (ret < 0) { + pr_err("ASoc OMAP3H1: can't set BT clock divider\n"); + return ret; + } + + return 0; +} + + +static int omap3h1_in_startup(struct snd_pcm_substream *substream) { + pr_info("ASoc OMAP3H1: omap3h1_in_startup"); gpio_set_value(mic_gpio_enable, 1); return clk_enable(per_96m_fck); } -static void omap3h1_shutdown(struct snd_pcm_substream *substream) +static void omap3h1_in_shutdown(struct snd_pcm_substream *substream) { + pr_info("ASoc OMAP3H1: omap3h1_in_shutdown"); 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 int omap3h1_out_startup(struct snd_pcm_substream *substream) +{ + pr_info("ASoc OMAP3H1: omap3h1_out_startup"); + return clk_enable(per_96m_fck); +} + +static void omap3h1_out_shutdown(struct snd_pcm_substream *substream) +{ + pr_info("ASoc OMAP3H1: omap3h1_out_shutdown"); + clk_disable(per_96m_fck); +} + +static struct snd_soc_ops omap3h1_in_ops = { + .hw_params = omap3h1_hw_in_params, + .startup = omap3h1_in_startup, + .shutdown = omap3h1_in_shutdown, }; -//static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = { -// SND_SOC_DAPM_MIC("Digital Mic", NULL), -//}; -// -//static const struct snd_soc_dapm_route dmic_audio_map[] = { -// {"DMic", NULL, "Digital Mic"}, -//}; +static struct snd_soc_ops omap3h1_out_ops = { + .hw_params = omap3h1_hw_out_params, + .startup = omap3h1_out_startup, + .shutdown = omap3h1_out_shutdown, +}; /* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3h1_dai = { - .name = "DMIC", - .stream_name = "DMIC Capture", - .cpu_dai_name = "omap-mcbsp.3", - .codec_dai_name = "dmic-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "dmic-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &omap3h1_ops, +static struct snd_soc_dai_link omap3h1_dai[] = { + { + .name = "DMIC", + .stream_name = "DMIC Capture", + .cpu_dai_name = "omap-mcbsp.3", + .codec_dai_name = "dmic-hifi", + .platform_name = "omap-pcm-audio", + .codec_name = "dmic-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ops = &omap3h1_in_ops, + }, + { + .name = "BT", + .stream_name = "BT Playback", + .cpu_dai_name = "omap-mcbsp.2", + .codec_dai_name = "omap3h1_bt_sco-pcm", + .platform_name = "omap-pcm-audio", + .codec_name = "omap3h1_bt_sco", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ops = &omap3h1_out_ops, + } }; /* Audio machine driver */ static struct snd_soc_card snd_soc_omap3h1 = { .name = "omap3h1", .owner = THIS_MODULE, - .dai_link = &omap3h1_dai, - .num_links = 1, - -// .dapm_widgets = dmic_dapm_widgets, -// .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets), -// .dapm_routes = dmic_audio_map, -// .num_dapm_routes = ARRAY_SIZE(dmic_audio_map), + .dai_link = omap3h1_dai, + .num_links = ARRAY_SIZE(omap3h1_dai), }; static int omap3h1_card_probe(struct platform_device *pdev) @@ -135,15 +191,24 @@ static int omap3h1_card_probe(struct platform_device *pdev) #ifdef CONFIG_OF if (node) { - struct device_node *dai_node; + struct device_node *dai_node1; + struct device_node *dai_node2; + + dai_node1 = of_parse_phandle(node, "olio,mcbsp_mic", 0); + if (!dai_node1) { + dev_err(&pdev->dev, "mcbsp3 node is not provided\n"); + return -EINVAL; + } + omap3h1_dai[0].cpu_dai_name = NULL; + omap3h1_dai[0].cpu_of_node = dai_node1; - dai_node = of_parse_phandle(node, "olio,mcbsp", 0); - if (!dai_node) { - dev_err(&pdev->dev, "mcbsp node is not provided\n"); + dai_node2 = of_parse_phandle(node, "olio,mcbsp_bt", 0); + if (!dai_node2) { + dev_err(&pdev->dev, "mcbsp2 node is not provided\n"); return -EINVAL; } - omap3h1_dai.cpu_dai_name = NULL; - omap3h1_dai.cpu_of_node = dai_node; + omap3h1_dai[1].cpu_dai_name = NULL; + omap3h1_dai[1].cpu_of_node = dai_node2; } else { dev_err(&pdev->dev, "Missing node\n"); @@ -191,52 +256,18 @@ static int omap3h1_card_remove(struct platform_device *pdev) return 0; } -/** - * 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, + .pm = &snd_soc_pm_ops, }, .probe = omap3h1_card_probe, .remove = omap3h1_card_remove, |