|
@@ -23,7 +23,6 @@
|
|
|
#include <dsp/spf-core.h>
|
|
|
#include <dsp/msm_audio_ion.h>
|
|
|
#include <sound/info.h>
|
|
|
-#include <dsp/apr_audio-v2.h>
|
|
|
#include <dsp/audio_prm.h>
|
|
|
|
|
|
#include "msm_common.h"
|
|
@@ -46,6 +45,7 @@ struct snd_card_pdata {
|
|
|
#define MAX_CODEC_DAI 8
|
|
|
#define TDM_SLOT_WIDTH_BITS 32
|
|
|
#define TDM_MAX_SLOTS 8
|
|
|
+#define MI2S_NUM_CHANNELS 2
|
|
|
|
|
|
static struct attribute device_state_attr = {
|
|
|
.name = "state",
|
|
@@ -244,28 +244,59 @@ static int get_intf_index(const char *stream_name)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
-static int get_intf_clk_id(int index)
|
|
|
+static int get_mi2s_clk_id(int index)
|
|
|
+{
|
|
|
+ int clk_id;
|
|
|
+
|
|
|
+ switch(index) {
|
|
|
+ case PRI_MI2S_TDM_AUXPCM:
|
|
|
+ clk_id = CLOCK_ID_PRI_MI2S_IBIT;
|
|
|
+ break;
|
|
|
+ case SEC_MI2S_TDM_AUXPCM:
|
|
|
+ clk_id = CLOCK_ID_SEP_MI2S_IBIT;
|
|
|
+ break;
|
|
|
+ case TER_MI2S_TDM_AUXPCM:
|
|
|
+ clk_id = CLOCK_ID_TER_MI2S_IBIT;
|
|
|
+ break;
|
|
|
+ case QUAT_MI2S_TDM_AUXPCM:
|
|
|
+ clk_id = CLOCK_ID_QUAD_MI2S_IBIT;
|
|
|
+ break;
|
|
|
+ case QUIN_MI2S_TDM_AUXPCM:
|
|
|
+ clk_id = CLOCK_ID_QUI_MI2S_IBIT;
|
|
|
+ break;
|
|
|
+ case SEN_MI2S_TDM_AUXPCM:
|
|
|
+ clk_id = CLOCK_ID_SEN_MI2S_IBIT;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ pr_err("%s: Invalid interface index: %d\n", __func__, index);
|
|
|
+ clk_id = -EINVAL;
|
|
|
+ }
|
|
|
+ pr_debug("%s: clk id: %d\n", __func__, clk_id);
|
|
|
+ return clk_id;
|
|
|
+}
|
|
|
+
|
|
|
+static int get_tdm_clk_id(int index)
|
|
|
{
|
|
|
int clk_id;
|
|
|
|
|
|
switch(index) {
|
|
|
case PRI_MI2S_TDM_AUXPCM:
|
|
|
- clk_id = Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT;
|
|
|
+ clk_id = CLOCK_ID_PRI_TDM_IBIT;
|
|
|
break;
|
|
|
case SEC_MI2S_TDM_AUXPCM:
|
|
|
- clk_id = Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT;
|
|
|
+ clk_id = CLOCK_ID_SEP_TDM_IBIT;
|
|
|
break;
|
|
|
case TER_MI2S_TDM_AUXPCM:
|
|
|
- clk_id = Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT;
|
|
|
+ clk_id = CLOCK_ID_TER_TDM_IBIT;
|
|
|
break;
|
|
|
case QUAT_MI2S_TDM_AUXPCM:
|
|
|
- clk_id = Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT;
|
|
|
+ clk_id = CLOCK_ID_QUAD_TDM_IBIT;
|
|
|
break;
|
|
|
case QUIN_MI2S_TDM_AUXPCM:
|
|
|
- clk_id = Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT;
|
|
|
+ clk_id = CLOCK_ID_QUI_TDM_IBIT;
|
|
|
break;
|
|
|
case SEN_MI2S_TDM_AUXPCM:
|
|
|
- clk_id = Q6AFE_LPASS_CLK_ID_SEN_TDM_IBIT;
|
|
|
+ clk_id = CLOCK_ID_SEN_TDM_IBIT;
|
|
|
break;
|
|
|
default:
|
|
|
pr_err("%s: Invalid interface index: %d\n", __func__, index);
|
|
@@ -281,13 +312,14 @@ int msm_common_snd_hw_params(struct snd_pcm_substream *substream,
|
|
|
int ret = 0;
|
|
|
int slot_width = TDM_SLOT_WIDTH_BITS;
|
|
|
int slots;
|
|
|
+ int sample_width;
|
|
|
unsigned int rate;
|
|
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
|
|
const char *stream_name = rtd->dai_link->stream_name;
|
|
|
struct snd_soc_card *card = rtd->card;
|
|
|
struct msm_common_pdata *pdata = msm_common_get_pdata(card);
|
|
|
int index = get_intf_index(stream_name);
|
|
|
- struct clk_cfg tdm_clk_cfg;
|
|
|
+ struct clk_cfg intf_clk_cfg;
|
|
|
|
|
|
dev_dbg(rtd->card->dev,
|
|
|
"%s: substream = %s stream = %d\n",
|
|
@@ -305,27 +337,66 @@ int msm_common_snd_hw_params(struct snd_pcm_substream *substream,
|
|
|
slots = pdata->tdm_max_slots;
|
|
|
rate = params_rate(params);
|
|
|
|
|
|
- tdm_clk_cfg.clk_id = get_intf_clk_id(index);
|
|
|
- if (tdm_clk_cfg.clk_id < 0) {
|
|
|
+ intf_clk_cfg.clk_id = get_tdm_clk_id(index);
|
|
|
+ if (intf_clk_cfg.clk_id < 0) {
|
|
|
ret = -EINVAL;
|
|
|
- pr_err("%s: Invalid clk id %d", __func__,
|
|
|
- tdm_clk_cfg.clk_id);
|
|
|
+ pr_err("%s: Invalid tdm clk id %d", __func__,
|
|
|
+ intf_clk_cfg.clk_id);
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
- tdm_clk_cfg.clk_freq_in_hz = rate * slot_width * slots;
|
|
|
- tdm_clk_cfg.clk_attri = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
|
|
|
- tdm_clk_cfg.clk_root = 0;
|
|
|
+ intf_clk_cfg.clk_freq_in_hz = rate * slot_width * slots;
|
|
|
+ intf_clk_cfg.clk_attri = CLOCK_ATTRIBUTE_COUPLE_NO;
|
|
|
+ intf_clk_cfg.clk_root = 0;
|
|
|
|
|
|
pr_debug("%s: clk_id :%d clk freq %d\n", __func__,
|
|
|
- tdm_clk_cfg.clk_id, tdm_clk_cfg.clk_freq_in_hz);
|
|
|
- ret = audio_prm_set_lpass_clk_cfg(&tdm_clk_cfg, 1);
|
|
|
+ intf_clk_cfg.clk_id, intf_clk_cfg.clk_freq_in_hz);
|
|
|
+ ret = audio_prm_set_lpass_clk_cfg(&intf_clk_cfg, 1);
|
|
|
if (ret < 0) {
|
|
|
pr_err("%s: prm lpass clk cfg set failed ret %d\n",
|
|
|
__func__, ret);
|
|
|
goto done;
|
|
|
}
|
|
|
+ } else if ((strnstr(stream_name, "MI2S", strlen(stream_name)))) {
|
|
|
+
|
|
|
+ intf_clk_cfg.clk_id = get_mi2s_clk_id(index);
|
|
|
+ if (intf_clk_cfg.clk_id < 0) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ pr_err("%s: Invalid mi2s clk id %d", __func__,
|
|
|
+ intf_clk_cfg.clk_id);
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ rate = params_rate(params);
|
|
|
+ switch (params_format(params)) {
|
|
|
+ case SNDRV_PCM_FORMAT_S24_LE:
|
|
|
+ case SNDRV_PCM_FORMAT_S24_3LE:
|
|
|
+ case SNDRV_PCM_FORMAT_S32_LE:
|
|
|
+ sample_width = 32;
|
|
|
+ break;
|
|
|
+ case SNDRV_PCM_FORMAT_S16_LE:
|
|
|
+ default:
|
|
|
+ sample_width = 16;
|
|
|
+ pr_debug("%s: bitwidth set to default : %d\n",
|
|
|
+ __func__, sample_width);
|
|
|
+ }
|
|
|
+ intf_clk_cfg.clk_freq_in_hz = rate *
|
|
|
+ MI2S_NUM_CHANNELS * sample_width;
|
|
|
+ intf_clk_cfg.clk_attri = CLOCK_ATTRIBUTE_COUPLE_NO;
|
|
|
+ intf_clk_cfg.clk_root = CLOCK_ROOT_DEFAULT;
|
|
|
+
|
|
|
+ pr_debug("%s: mi2s clk_id :%d clk freq %d\n", __func__,
|
|
|
+ intf_clk_cfg.clk_id, intf_clk_cfg.clk_freq_in_hz);
|
|
|
+ ret = audio_prm_set_lpass_clk_cfg(&intf_clk_cfg, 1);
|
|
|
+ if (ret < 0) {
|
|
|
+ pr_err("%s: prm lpass mi2s clk cfg set failed ret %d\n",
|
|
|
+ __func__, ret);
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ pr_err("%s: invalid stream name: %s\n", __func__,
|
|
|
+ stream_name);
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
done:
|
|
|
mutex_unlock(&pdata->lock[index]);
|
|
@@ -379,9 +450,9 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream)
|
|
|
struct msm_common_pdata *pdata = msm_common_get_pdata(card);
|
|
|
const char *stream_name = rtd->dai_link->stream_name;
|
|
|
int index = get_intf_index(stream_name);
|
|
|
- struct clk_cfg tdm_clk_cfg;
|
|
|
+ struct clk_cfg intf_clk_cfg;
|
|
|
|
|
|
- memset(&tdm_clk_cfg, 0, sizeof(struct clk_cfg));
|
|
|
+ memset(&intf_clk_cfg, 0, sizeof(struct clk_cfg));
|
|
|
pr_debug("%s(): substream = %s stream = %d\n", __func__,
|
|
|
substream->name, substream->stream);
|
|
|
|
|
@@ -398,11 +469,20 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream)
|
|
|
atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]);
|
|
|
if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) {
|
|
|
if ((strnstr(stream_name, "TDM", strlen(stream_name)))) {
|
|
|
- tdm_clk_cfg.clk_id = get_intf_clk_id(index);
|
|
|
- ret = audio_prm_set_lpass_clk_cfg(&tdm_clk_cfg, 0);
|
|
|
+ intf_clk_cfg.clk_id = get_tdm_clk_id(index);
|
|
|
+ ret = audio_prm_set_lpass_clk_cfg(&intf_clk_cfg, 0);
|
|
|
if (ret < 0)
|
|
|
pr_err("%s: prm clk cfg set failed ret %d\n",
|
|
|
__func__, ret);
|
|
|
+ } else if((strnstr(stream_name, "MI2S", strlen(stream_name)))) {
|
|
|
+ intf_clk_cfg.clk_id = get_mi2s_clk_id(index);
|
|
|
+ ret = audio_prm_set_lpass_clk_cfg(&intf_clk_cfg, 0);
|
|
|
+ if (ret < 0)
|
|
|
+ pr_err("%s: prm mi2s clk cfg disable failed ret %d\n",
|
|
|
+ __func__, ret);
|
|
|
+ } else {
|
|
|
+ pr_err("%s: invalid stream name: %s\n",
|
|
|
+ __func__, stream_name);
|
|
|
}
|
|
|
ret = msm_cdc_pinctrl_select_sleep_state(
|
|
|
pdata->mi2s_gpio_p[index]);
|