diff options
| author | xnikdor <Mykyta.Dorokhin@globallogic.com> | 2015-08-19 14:23:24 +0300 |
|---|---|---|
| committer | mattis fjallstrom <mattis@acm.org> | 2016-01-14 12:19:53 -0800 |
| commit | 704efd6edcc5696c09670da6aa78c775deb9cf44 (patch) | |
| tree | 8bf1c5f9c2bfcda8caba16c2d78a588b5e803803 | |
| parent | a2cf73d74dc87c054c3ca329eba11299f2efb95f (diff) | |
| download | olio-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.dts | 3 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1.c | 9 | ||||
| -rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/omap3h1_bt_sco.c | 74 | ||||
| -rw-r--r-- | sound/soc/omap/Kconfig | 1 | ||||
| -rw-r--r-- | sound/soc/omap/omap3h1.c | 197 |
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, |