diff options
Diffstat (limited to 'sound')
| -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 | 
5 files changed, 195 insertions, 83 deletions
| 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, |