diff options
Diffstat (limited to 'sound/soc/msm/msm8998.c')
| -rw-r--r-- | sound/soc/msm/msm8998.c | 181 |
1 files changed, 170 insertions, 11 deletions
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 041a91e28988..f6a5d1344568 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -496,6 +496,8 @@ static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_chs, mi2s_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_chs, mi2s_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_chs, mi2s_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(hifi_function, hifi_text); static struct platform_device *spdev; @@ -2263,6 +2265,54 @@ static int mi2s_get_sample_rate(int value) return sample_rate; } +static int mi2s_get_format(int value) +{ + int format; + + switch (value) { + case 0: + format = SNDRV_PCM_FORMAT_S16_LE; + break; + case 1: + format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 2: + format = SNDRV_PCM_FORMAT_S24_3LE; + break; + case 3: + format = SNDRV_PCM_FORMAT_S32_LE; + break; + default: + format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + return format; +} + +static int mi2s_get_format_value(int format) +{ + int value; + + switch (format) { + case SNDRV_PCM_FORMAT_S16_LE: + value = 0; + break; + case SNDRV_PCM_FORMAT_S24_LE: + value = 1; + break; + case SNDRV_PCM_FORMAT_S24_3LE: + value = 2; + break; + case SNDRV_PCM_FORMAT_S32_LE: + value = 3; + break; + default: + value = 0; + break; + } + return value; +} + static int mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -2395,6 +2445,78 @@ static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol, return 1; } +static int msm_mi2s_rx_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + mi2s_get_format_value(mi2s_rx_cfg[idx].bit_format); + + pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__, + idx, mi2s_rx_cfg[idx].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_mi2s_rx_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + mi2s_rx_cfg[idx].bit_format = + mi2s_get_format(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__, + idx, mi2s_rx_cfg[idx].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_mi2s_tx_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + mi2s_get_format_value(mi2s_tx_cfg[idx].bit_format); + + pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__, + idx, mi2s_tx_cfg[idx].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_mi2s_tx_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + mi2s_tx_cfg[idx].bit_format = + mi2s_get_format(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__, + idx, mi2s_tx_cfg[idx].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + static int msm_hifi_ctrl(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); @@ -2647,6 +2769,22 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put), SOC_ENUM_EXT("QUAT_MI2S_TX Channels", quat_mi2s_tx_chs, msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put), + SOC_ENUM_EXT("PRIM_MI2S_RX Format", mi2s_rx_format, + msm_mi2s_rx_format_get, msm_mi2s_rx_format_put), + SOC_ENUM_EXT("PRIM_MI2S_TX Format", mi2s_tx_format, + msm_mi2s_tx_format_get, msm_mi2s_tx_format_put), + SOC_ENUM_EXT("SEC_MI2S_RX Format", mi2s_rx_format, + msm_mi2s_rx_format_get, msm_mi2s_rx_format_put), + SOC_ENUM_EXT("SEC_MI2S_TX Format", mi2s_tx_format, + msm_mi2s_tx_format_get, msm_mi2s_tx_format_put), + SOC_ENUM_EXT("TERT_MI2S_RX Format", mi2s_rx_format, + msm_mi2s_rx_format_get, msm_mi2s_rx_format_put), + SOC_ENUM_EXT("TERT_MI2S_TX Format", mi2s_tx_format, + msm_mi2s_tx_format_get, msm_mi2s_tx_format_put), + SOC_ENUM_EXT("QUAT_MI2S_RX Format", mi2s_rx_format, + msm_mi2s_rx_format_get, msm_mi2s_rx_format_put), + SOC_ENUM_EXT("QUAT_MI2S_TX Format", mi2s_tx_format, + msm_mi2s_tx_format_get, msm_mi2s_tx_format_put), SOC_ENUM_EXT("HiFi Function", hifi_function, msm_hifi_get, msm_hifi_put), }; @@ -3111,48 +3249,64 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, break; case MSM_BACKEND_DAI_PRI_MI2S_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_rx_cfg[PRIM_MI2S].bit_format); rate->min = rate->max = mi2s_rx_cfg[PRIM_MI2S].sample_rate; channels->min = channels->max = mi2s_rx_cfg[PRIM_MI2S].channels; break; case MSM_BACKEND_DAI_PRI_MI2S_TX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_tx_cfg[PRIM_MI2S].bit_format); rate->min = rate->max = mi2s_tx_cfg[PRIM_MI2S].sample_rate; channels->min = channels->max = mi2s_tx_cfg[PRIM_MI2S].channels; break; case MSM_BACKEND_DAI_SECONDARY_MI2S_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_rx_cfg[SEC_MI2S].bit_format); rate->min = rate->max = mi2s_rx_cfg[SEC_MI2S].sample_rate; channels->min = channels->max = mi2s_rx_cfg[SEC_MI2S].channels; break; case MSM_BACKEND_DAI_SECONDARY_MI2S_TX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_tx_cfg[SEC_MI2S].bit_format); rate->min = rate->max = mi2s_tx_cfg[SEC_MI2S].sample_rate; channels->min = channels->max = mi2s_tx_cfg[SEC_MI2S].channels; break; case MSM_BACKEND_DAI_TERTIARY_MI2S_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_rx_cfg[TERT_MI2S].bit_format); rate->min = rate->max = mi2s_rx_cfg[TERT_MI2S].sample_rate; channels->min = channels->max = mi2s_rx_cfg[TERT_MI2S].channels; break; case MSM_BACKEND_DAI_TERTIARY_MI2S_TX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_tx_cfg[TERT_MI2S].bit_format); rate->min = rate->max = mi2s_tx_cfg[TERT_MI2S].sample_rate; channels->min = channels->max = mi2s_tx_cfg[TERT_MI2S].channels; break; case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_rx_cfg[QUAT_MI2S].bit_format); rate->min = rate->max = mi2s_rx_cfg[QUAT_MI2S].sample_rate; channels->min = channels->max = mi2s_rx_cfg[QUAT_MI2S].channels; break; case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + mi2s_tx_cfg[QUAT_MI2S].bit_format); rate->min = rate->max = mi2s_tx_cfg[QUAT_MI2S].sample_rate; channels->min = channels->max = mi2s_tx_cfg[QUAT_MI2S].channels; @@ -3972,6 +4126,7 @@ static u32 get_mi2s_bits_per_sample(u32 bit_format) u32 bit_per_sample; switch (bit_format) { + case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S24_3LE: case SNDRV_PCM_FORMAT_S24_LE: bit_per_sample = 32; @@ -4000,9 +4155,6 @@ static void update_mi2s_clk_val(int dai_id, int stream) mi2s_clk[dai_id].clk_freq_in_hz = mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample; } - - if (!mi2s_intf_conf[dai_id].msm_is_mi2s_master) - mi2s_clk[dai_id].clk_freq_in_hz = 0; } static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable) @@ -4051,6 +4203,13 @@ static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, ret = -EINVAL; goto err; } + + if (pinctrl_info->pinctrl == NULL) { + pr_err("%s: pinctrl_info->pinctrl is NULL\n", __func__); + ret = -EINVAL; + goto err; + } + curr_state = pinctrl_info->curr_state; pinctrl_info->curr_state = new_state; pr_debug("%s: curr_state = %s new_state = %s\n", __func__, @@ -4319,6 +4478,7 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; + int ret_pinctrl = 0; dev_dbg(rtd->card->dev, "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", @@ -4333,11 +4493,10 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) goto done; } if (index == QUAT_MI2S) { - ret = msm_set_pinctrl(pinctrl_info, STATE_MI2S_ACTIVE); - if (ret) { + ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_MI2S_ACTIVE); + if (ret_pinctrl) { pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", - __func__, ret); - goto done; + __func__, ret_pinctrl); } } @@ -4396,6 +4555,7 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; + int ret_pinctrl = 0; pr_debug("%s(): substream = %s stream = %d\n", __func__, substream->name, substream->stream); @@ -4416,10 +4576,10 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) mutex_unlock(&mi2s_intf_conf[index].lock); if (index == QUAT_MI2S) { - ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); - if (ret) + ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); + if (ret_pinctrl) pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", - __func__, ret); + __func__, ret_pinctrl); } } @@ -5239,7 +5399,6 @@ static struct snd_soc_dai_link msm_tasha_fe_dai_links[] = { .platform_name = "msm-pcm-hostless", .dynamic = 1, .dpcm_playback = 1, - .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, |
