[alsa-devel] [PATCH v2 8/9] ASoC: mediatek: add BT implementation

2016-06-02 Thread Garlic Tseng
Add BT implementation for mt2701 platform driver.

Signed-off-by: Garlic Tseng 
---
 sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 141 +
 1 file changed, 141 insertions(+)

diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c 
b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index 4c22ca0..9215b71 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -346,6 +346,88 @@ static int mt2701_afe_i2s_set_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
return 0;
 }
 
+static int mt2701_btmrg_startup(struct snd_pcm_substream *substream,
+   struct snd_soc_dai *dai)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+   struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+   regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
+  AUDIO_TOP_CON4_PDN_MRGIF, 0);
+
+   afe_priv->mrg_enable[substream->stream] = 1;
+   return 0;
+}
+
+static int mt2701_btmrg_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+   int stream_fs;
+   u32 val, msk;
+
+   pr_debug("%s() cpu_dai id %d\n", __func__, dai->id);
+   stream_fs = params_rate(params);
+
+   if ((stream_fs != 8000) && (stream_fs != 16000)) {
+   pr_err("%s() btmgr not supprt this stream_fs %d\n",
+  __func__, stream_fs);
+   return -EINVAL;
+   }
+
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_I2S_MODE_MASK,
+  AFE_MRGIF_CON_I2S_MODE_32K);
+
+   val = AFE_DAIBT_CON0_BT_FUNC_EN | AFE_DAIBT_CON0_BT_FUNC_RDY
+ | AFE_DAIBT_CON0_MRG_USE;
+   msk = val;
+
+   if (stream_fs == 16000)
+   val |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN;
+
+   msk |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN;
+
+   regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, msk, val);
+
+   regmap_update_bits(afe->regmap, AFE_DAIBT_CON0,
+  AFE_DAIBT_CON0_DAIBT_EN,
+  AFE_DAIBT_CON0_DAIBT_EN);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_I2S_EN,
+  AFE_MRGIF_CON_MRG_I2S_EN);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_EN,
+  AFE_MRGIF_CON_MRG_EN);
+   return 0;
+}
+
+static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+   struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+   pr_debug("%s() cpu_dai id %d\n", __func__, dai->id);
+   /* if the other direction stream is not occupied */
+   if (!afe_priv->mrg_enable[!substream->stream]) {
+   regmap_update_bits(afe->regmap, AFE_DAIBT_CON0,
+  AFE_DAIBT_CON0_DAIBT_EN, 0);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_EN, 0);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_I2S_EN, 0);
+   regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
+  AUDIO_TOP_CON4_PDN_MRGIF,
+  AUDIO_TOP_CON4_PDN_MRGIF);
+   }
+   afe_priv->mrg_enable[substream->stream] = 0;
+}
+
 static int mt2701_simple_fe_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
 {
@@ -529,6 +611,13 @@ static const struct snd_soc_dai_ops mt2701_afe_i2s_ops = {
.set_fmt= mt2701_afe_i2s_set_fmt,
 };
 
+/* MRG BE DAIs*/
+static struct snd_soc_dai_ops mt2701_btmrg_ops = {
+   .startup = mt2701_btmrg_startup,
+   .shutdown = mt2701_btmrg_shutdown,
+   .hw_params = mt2701_btmrg_hw_params,
+};
+
 static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
/* FE DAIs: memory intefaces to CPU */
{
@@ -579,6 +668,36 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
},
.ops = _single_memif_dai_ops,
},
+   {
+   .name = "PCM_BT_DL",
+   .id = MT2701_MEMIF_DLBT,
+   .suspend = mtk_afe_dai_suspend,
+   .resume = mtk_afe_dai_resume,
+   .playback = {
+   

[alsa-devel] [PATCH v2 8/9] ASoC: mediatek: add BT implementation

2016-06-02 Thread Garlic Tseng
Add BT implementation for mt2701 platform driver.

Signed-off-by: Garlic Tseng 
---
 sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 141 +
 1 file changed, 141 insertions(+)

diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c 
b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index 4c22ca0..9215b71 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -346,6 +346,88 @@ static int mt2701_afe_i2s_set_fmt(struct snd_soc_dai *dai, 
unsigned int fmt)
return 0;
 }
 
+static int mt2701_btmrg_startup(struct snd_pcm_substream *substream,
+   struct snd_soc_dai *dai)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+   struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+   regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
+  AUDIO_TOP_CON4_PDN_MRGIF, 0);
+
+   afe_priv->mrg_enable[substream->stream] = 1;
+   return 0;
+}
+
+static int mt2701_btmrg_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+   int stream_fs;
+   u32 val, msk;
+
+   pr_debug("%s() cpu_dai id %d\n", __func__, dai->id);
+   stream_fs = params_rate(params);
+
+   if ((stream_fs != 8000) && (stream_fs != 16000)) {
+   pr_err("%s() btmgr not supprt this stream_fs %d\n",
+  __func__, stream_fs);
+   return -EINVAL;
+   }
+
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_I2S_MODE_MASK,
+  AFE_MRGIF_CON_I2S_MODE_32K);
+
+   val = AFE_DAIBT_CON0_BT_FUNC_EN | AFE_DAIBT_CON0_BT_FUNC_RDY
+ | AFE_DAIBT_CON0_MRG_USE;
+   msk = val;
+
+   if (stream_fs == 16000)
+   val |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN;
+
+   msk |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN;
+
+   regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, msk, val);
+
+   regmap_update_bits(afe->regmap, AFE_DAIBT_CON0,
+  AFE_DAIBT_CON0_DAIBT_EN,
+  AFE_DAIBT_CON0_DAIBT_EN);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_I2S_EN,
+  AFE_MRGIF_CON_MRG_I2S_EN);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_EN,
+  AFE_MRGIF_CON_MRG_EN);
+   return 0;
+}
+
+static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
+   struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+   pr_debug("%s() cpu_dai id %d\n", __func__, dai->id);
+   /* if the other direction stream is not occupied */
+   if (!afe_priv->mrg_enable[!substream->stream]) {
+   regmap_update_bits(afe->regmap, AFE_DAIBT_CON0,
+  AFE_DAIBT_CON0_DAIBT_EN, 0);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_EN, 0);
+   regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
+  AFE_MRGIF_CON_MRG_I2S_EN, 0);
+   regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
+  AUDIO_TOP_CON4_PDN_MRGIF,
+  AUDIO_TOP_CON4_PDN_MRGIF);
+   }
+   afe_priv->mrg_enable[substream->stream] = 0;
+}
+
 static int mt2701_simple_fe_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
 {
@@ -529,6 +611,13 @@ static const struct snd_soc_dai_ops mt2701_afe_i2s_ops = {
.set_fmt= mt2701_afe_i2s_set_fmt,
 };
 
+/* MRG BE DAIs*/
+static struct snd_soc_dai_ops mt2701_btmrg_ops = {
+   .startup = mt2701_btmrg_startup,
+   .shutdown = mt2701_btmrg_shutdown,
+   .hw_params = mt2701_btmrg_hw_params,
+};
+
 static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
/* FE DAIs: memory intefaces to CPU */
{
@@ -579,6 +668,36 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
},
.ops = _single_memif_dai_ops,
},
+   {
+   .name = "PCM_BT_DL",
+   .id = MT2701_MEMIF_DLBT,
+   .suspend = mtk_afe_dai_suspend,
+   .resume = mtk_afe_dai_resume,
+   .playback = {
+   .stream_name = "DLBT",
+