diff options
Diffstat (limited to 'sound/soc/omap/omap3h1.c')
| -rw-r--r-- | sound/soc/omap/omap3h1.c | 197 | 
1 files changed, 114 insertions, 83 deletions
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,  |