summaryrefslogtreecommitdiff
path: root/sound/soc/omap
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap')
-rw-r--r--sound/soc/omap/Kconfig1
-rw-r--r--sound/soc/omap/omap3h1.c197
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,