summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxnikdor <Mykyta.Dorokhin@globallogic.com>2015-08-19 14:23:24 +0300
committermattis fjallstrom <mattis@acm.org>2016-01-14 12:19:53 -0800
commit704efd6edcc5696c09670da6aa78c775deb9cf44 (patch)
tree8bf1c5f9c2bfcda8caba16c2d78a588b5e803803
parenta2cf73d74dc87c054c3ca329eba11299f2efb95f (diff)
downloadolio-linux-3.10-master.tar.xz
olio-linux-3.10-master.zip
Audio To BT: added capture and playback alsa devicesmaster
Mattis: Rebased to android-3.10-bringup. Change-Id: Id1660d1f1a45ee039609955efbc53b75364b5ca1
-rw-r--r--arch/arm/boot/dts/omap3_h1.dts3
-rw-r--r--arch/arm/mach-omap2/board-omap3h1.c9
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/omap3h1_bt_sco.c74
-rw-r--r--sound/soc/omap/Kconfig1
-rw-r--r--sound/soc/omap/omap3h1.c197
7 files changed, 204 insertions, 86 deletions
diff --git a/arch/arm/boot/dts/omap3_h1.dts b/arch/arm/boot/dts/omap3_h1.dts
index ee19b23f0cc..326b3ffd486 100644
--- a/arch/arm/boot/dts/omap3_h1.dts
+++ b/arch/arm/boot/dts/omap3_h1.dts
@@ -91,7 +91,8 @@
sound {
compatible = "olio,omap-soc-omap3h1";
- olio,mcbsp = <&mcbsp3>;
+ olio,mcbsp_bt = <&mcbsp2>;
+ olio,mcbsp_mic = <&mcbsp3>;
olio,mic_enable = <&gpio5 18 0>;
};
};
diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c
index ad40bd6d90e..7915962e45b 100644
--- a/arch/arm/mach-omap2/board-omap3h1.c
+++ b/arch/arm/mach-omap2/board-omap3h1.c
@@ -254,6 +254,10 @@ static struct platform_device omap3h1_dmic_codec = {
.id = -1,
};
+static struct platform_device omap3h1_bt_codec = {
+ .name = "omap3h1_bt_sco",
+ .id = -1,
+};
/* --------------------------------------------------------------------------- */
/* USB settings
@@ -473,9 +477,10 @@ static int __init omap3_h1_i2c_init(void)
static struct platform_device *omap3h1_devices[] __initdata = {
- &bcm20702_bluetooth_device,
- &nop_phy_device,
+ &bcm20702_bluetooth_device,
+ &nop_phy_device,
&omap3h1_dmic_codec,
+ &omap3h1_bt_codec,
};
static void __init omap3_h1_init(void)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 50ff7ca10a9..113ee1f928c 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -41,6 +41,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C
select SND_SOC_DFBMCS320
+ select SND_SOC_OMAP3H1_BT_SCO
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
@@ -266,6 +267,9 @@ config SND_SOC_DA9055
config SND_SOC_DFBMCS320
tristate
+config SND_SOC_OMAP3H1_BT_SCO
+ tristate
+
config SND_SOC_DMIC
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 39747d34c41..8e7bb4d4cbe 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -29,6 +29,7 @@ snd-soc-da7213-objs := da7213.o
snd-soc-da732x-objs := da732x.o
snd-soc-da9055-objs := da9055.o
snd-soc-dfbmcs320-objs := dfbmcs320.o
+snd-soc-omap3h1_bt_sco-objs := omap3h1_bt_sco.o
snd-soc-dmic-objs := dmic.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
@@ -157,6 +158,7 @@ obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o
+obj-$(CONFIG_SND_SOC_OMAP3H1_BT_SCO) += snd-soc-omap3h1_bt_sco.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
diff --git a/sound/soc/codecs/omap3h1_bt_sco.c b/sound/soc/codecs/omap3h1_bt_sco.c
new file mode 100644
index 00000000000..f72f004f64c
--- /dev/null
+++ b/sound/soc/codecs/omap3h1_bt_sco.c
@@ -0,0 +1,74 @@
+/*
+ * Driver for the DFBM-CS320 bluetooth module
+ * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <sound/soc.h>
+
+int omap3h1_bt_sco_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+ printk ("OMAP3H1:ASoc %s:%s starting\n", __FILE__, __FUNCTION__);
+ return 0;
+}
+
+void omap3h1_bt_sco_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+ printk ("OMAP3H1:ASoc %s:%s shutting down\n", __FILE__, __FUNCTION__);
+}
+
+static struct snd_soc_dai_ops omap3h1_bt_sco_dai_ops = {
+ .startup = omap3h1_bt_sco_dai_startup,
+ .shutdown = omap3h1_bt_sco_dai_shutdown,
+};
+
+static struct snd_soc_dai_driver omap3h1_bt_sco_dai = {
+ .name = "omap3h1_bt_sco-pcm",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &omap3h1_bt_sco_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_omap3h1_bt_sco;
+
+static int omap3h1_bt_sco_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_omap3h1_bt_sco,
+ &omap3h1_bt_sco_dai, 1);
+}
+
+static int omap3h1_bt_sco_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+
+ return 0;
+}
+
+
+static struct platform_driver omap3h1_bt_sco = {
+ .driver = {
+ .name = "omap3h1_bt_sco",
+ .owner = THIS_MODULE,
+ },
+ .probe = omap3h1_bt_sco_probe,
+ .remove = omap3h1_bt_sco_remove,
+};
+
+module_platform_driver(omap3h1_bt_sco);
+
+MODULE_AUTHOR("Evan Wilson <evan@oliodevices.com");
+MODULE_DESCRIPTION("OMAP3 H1 ALSA SoC codec driver");
+MODULE_LICENSE("GPL"); \ No newline at end of file
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,