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 à :
@@ -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]);
|
||||
|
Référencer dans un nouveau ticket
Bloquer un utilisateur