ASoC: msm: Changes in machine driver to enable mclk

Provide the support to enable MCLK output to external
audio connections. Also, update configuration to set
bit clock as EBIT in slave mode.

CRs-Fixed: 1094763
Change-Id: If07f31a6c37c7b8b23eb74b25a1e15990043cb92
Signed-off-by: Tanya Dixit <tdixit@codeaurora.org>
Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
This commit is contained in:
Tanya Dixit 2016-12-08 22:25:56 +05:30 committed by Laxminath Kasam
parent 03e601544b
commit bc6d0c8cdd
3 changed files with 98 additions and 6 deletions

View file

@ -1772,6 +1772,10 @@ Optional Properties:
- qcom,msm-mi2s-master: This property is used to inform machine driver
if MSM is the clock master of mi2s. 1 means master and 0 means slave. The
first entry is primary mi2s; the second entry is secondary mi2s, and so on.
- qcom,msm-mi2s-ext-mclk: This property is used to inform machine driver
if MCLK from MSM is used for any external audio connections. 1 means used
as external mclk source and 0 indicate not used. The first entry is
primary mclk; the second entry is secondary mclk, and so on.
- reg: This property provides the AUX PCM/MI2S mux select register addresses
and size.
- reg_names: This property provides the name of the AUX PCM/MI2S mux select
@ -1812,6 +1816,7 @@ Example:
qcom,mi2s-audio-intf;
qcom,auxpcm-audio-intf;
qcom,msm-mi2s-master = <1>, <0>, <1>, <1>;
qcom,msm-mi2s-ext-mclk = <1>, <1>, <0>, <1>;
reg = <0x1711a000 0x4>,
<0x1711b000 0x4>,
<0x1711c000 0x4>,

View file

@ -169,6 +169,7 @@ struct mi2s_conf {
struct mutex lock;
u32 ref_cnt;
u32 msm_is_mi2s_master;
u32 msm_is_ext_mclk;
};
struct auxpcm_conf {
@ -176,6 +177,13 @@ struct auxpcm_conf {
u32 ref_cnt;
};
static u32 mi2s_ebit_clk[MI2S_MAX] = {
Q6AFE_LPASS_CLK_ID_PRI_MI2S_EBIT,
Q6AFE_LPASS_CLK_ID_SEC_MI2S_EBIT,
Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT,
Q6AFE_LPASS_CLK_ID_QUAD_MI2S_EBIT
};
struct msm_wsa881x_dev_info {
struct device_node *of_node;
u32 index;
@ -340,6 +348,43 @@ static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
}
};
static struct afe_clk_set mi2s_mclk[MI2S_MAX] = {
{
AFE_API_VERSION_I2S_CONFIG,
Q6AFE_LPASS_CLK_ID_MCLK_1,
Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
0,
},
{
AFE_API_VERSION_I2S_CONFIG,
Q6AFE_LPASS_CLK_ID_MCLK_2,
Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
0,
},
{
AFE_API_VERSION_I2S_CONFIG,
Q6AFE_LPASS_CLK_ID_MCLK_3,
Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
0,
},
{
AFE_API_VERSION_I2S_CONFIG,
Q6AFE_LPASS_CLK_ID_MCLK_4,
Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
0,
}
};
static struct mi2s_aux_pcm_common_conf mi2s_auxpcm_conf[PCM_I2S_SEL_MAX];
static struct mi2s_conf mi2s_intf_conf[MI2S_MAX];
static struct auxpcm_conf auxpcm_intf_conf[AUX_PCM_MAX];
@ -2095,6 +2140,7 @@ int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
int ret = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int port_id = msm_get_port_id(rtd->dai_link->be_id);
int index = cpu_dai->id;
unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
@ -2117,6 +2163,11 @@ int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
*/
mutex_lock(&mi2s_intf_conf[index].lock);
if (++mi2s_intf_conf[index].ref_cnt == 1) {
/* Check if msm needs to provide the clock to the interface */
if (!mi2s_intf_conf[index].msm_is_mi2s_master) {
mi2s_clk[index].clk_id = mi2s_ebit_clk[index];
fmt = SND_SOC_DAIFMT_CBM_CFM;
}
ret = msm_mi2s_set_sclk(substream, true);
if (IS_ERR_VALUE(ret)) {
dev_err(rtd->card->dev,
@ -2136,9 +2187,6 @@ int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
ret = -EINVAL;
goto clk_off;
}
/* Check if msm needs to provide the clock to the interface */
if (!mi2s_intf_conf[index].msm_is_mi2s_master)
fmt = SND_SOC_DAIFMT_CBM_CFM;
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (IS_ERR_VALUE(ret)) {
dev_err(rtd->card->dev,
@ -2146,7 +2194,21 @@ int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
__func__, index, ret);
goto clk_off;
}
if (mi2s_intf_conf[index].msm_is_ext_mclk) {
mi2s_mclk[index].enable = 1;
pr_debug("%s: Enabling mclk, clk_freq_in_hz = %u\n",
__func__, mi2s_mclk[index].clk_freq_in_hz);
ret = afe_set_lpass_clock_v2(port_id,
&mi2s_mclk[index]);
if (ret < 0) {
pr_err("%s: afe lpass mclk failed, err:%d\n",
__func__, ret);
goto clk_off;
}
}
}
mutex_unlock(&mi2s_intf_conf[index].lock);
return 0;
clk_off:
if (IS_ERR_VALUE(ret))
msm_mi2s_set_sclk(substream, false);
@ -2168,6 +2230,7 @@ void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
{
int ret;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int port_id = msm_get_port_id(rtd->dai_link->be_id);
int index = rtd->cpu_dai->id;
pr_debug("%s(): substream = %s stream = %d\n", __func__,
@ -2185,6 +2248,17 @@ void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
__func__, index, ret);
mi2s_intf_conf[index].ref_cnt++;
}
if (mi2s_intf_conf[index].msm_is_ext_mclk) {
mi2s_mclk[index].enable = 0;
pr_debug("%s: Disabling mclk, clk_freq_in_hz = %u\n",
__func__, mi2s_mclk[index].clk_freq_in_hz);
ret = afe_set_lpass_clock_v2(port_id,
&mi2s_mclk[index]);
if (ret < 0) {
pr_err("%s: mclk disable failed for MCLK (%d); ret=%d\n",
__func__, index, ret);
}
}
}
mutex_unlock(&mi2s_intf_conf[index].lock);
}
@ -2601,6 +2675,7 @@ static void i2s_auxpcm_init(struct platform_device *pdev)
struct resource *muxsel;
int count;
u32 mi2s_master_slave[MI2S_MAX];
u32 mi2s_ext_mclk[MI2S_MAX];
int ret;
char *str[PCM_I2S_SEL_MAX] = {
"lpaif_pri_mode_muxsel",
@ -2634,8 +2709,8 @@ static void i2s_auxpcm_init(struct platform_device *pdev)
}
ret = of_property_read_u32_array(pdev->dev.of_node,
"qcom,msm-mi2s-master",
mi2s_master_slave, MI2S_MAX);
"qcom,msm-mi2s-master",
mi2s_master_slave, MI2S_MAX);
if (ret) {
dev_dbg(&pdev->dev, "%s: no qcom,msm-mi2s-master in DT node\n",
__func__);
@ -2645,6 +2720,18 @@ static void i2s_auxpcm_init(struct platform_device *pdev)
mi2s_master_slave[count];
}
}
ret = of_property_read_u32_array(pdev->dev.of_node,
"qcom,msm-mi2s-ext-mclk",
mi2s_ext_mclk, MI2S_MAX);
if (ret) {
dev_dbg(&pdev->dev, "%s: no qcom,msm-mi2s-ext-mclk in DT node\n",
__func__);
} else {
for (count = 0; count < MI2S_MAX; count++)
mi2s_intf_conf[count].msm_is_ext_mclk =
mi2s_ext_mclk[count];
}
}
static void i2s_auxpcm_deinit(void)

View file

@ -3033,7 +3033,7 @@ static int msm_internal_init(struct platform_device *pdev,
AFE_API_VERSION_I2S_CONFIG;
pdata->digital_cdc_core_clk.clk_id =
Q6AFE_LPASS_CLK_ID_INT_MCLK_0;
pdata->digital_cdc_core_clk.clk_freq_in_hz = 0;
pdata->digital_cdc_core_clk.clk_freq_in_hz = pdata->mclk_freq;
pdata->digital_cdc_core_clk.clk_attri =
Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
pdata->digital_cdc_core_clk.clk_root =