asoc: common: configure mi2s interface clocks

Add support for mi2s interface clock configuration.

Change-Id: I439de17670d9521898d8bde893255025eceab84d
Signed-off-by: Prasad Kumpatla <pkumpatl@codeaurora.org>
Cette révision appartient à :
Prasad Kumpatla
2021-08-05 16:42:48 +05:30
Parent 043966829b
révision d8f2af06e6
2 fichiers modifiés avec 114 ajouts et 22 suppressions

Voir le fichier

@@ -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]);