diff --git a/asoc/msm_common.c b/asoc/msm_common.c index 207f2ef050..002ef98607 100644 --- a/asoc/msm_common.c +++ b/asoc/msm_common.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #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]); diff --git a/include/dsp/audio_prm.h b/include/dsp/audio_prm.h index 0bdfe649b4..8bb7925850 100644 --- a/include/dsp/audio_prm.h +++ b/include/dsp/audio_prm.h @@ -292,6 +292,12 @@ typedef struct prm_cmd_request_hw_core_t #define CLOCK_ID_SEN_MI2S_EBIT 0x10C +/** Clock ID of the septenary MI2S IBIT. */ +#define CLOCK_ID_SEP_MI2S_IBIT 0x10D + +/** Clock ID of the septenary MI2S EBIT. */ +#define CLOCK_ID_SEP_MI2S_EBIT 0x10E + /** ID of I2S IBIT clock 0 that is used with integrated codec. */ #define CLOCK_ID_INT0_I2S_IBIT 0x10D @@ -424,6 +430,12 @@ typedef struct prm_cmd_request_hw_core_t #define CLOCK_ID_SEN_TDM_EBIT 0x20C +/** Clock ID of the septenary TDM IBIT. */ +#define CLOCK_ID_SEP_TDM_IBIT 0x20D + +/** Clock ID of the septenary TDM EBIT. */ +#define CLOCK_ID_SEP_TDM_EBIT 0x20E + /** Clock ID for MCLK 1. */ #define CLOCK_ID_MCLK_1 0x300