diff options
author | Shiv Maliyappanahalli <smaliyap@codeaurora.org> | 2016-06-28 17:42:40 -0700 |
---|---|---|
committer | Kyle Yan <kyan@codeaurora.org> | 2016-07-11 14:26:14 -0700 |
commit | 87b1536fb347209143e306f5b56b8dc23282d192 (patch) | |
tree | 6c061d714bf0ac0eb939a6573a4f4196e5ed5204 | |
parent | 62101aeaa9a0f369779db6138967f7b08efe68bc (diff) |
msmcobalt: enable audio over HDMI
Add HDMI audio back end and associated apis to
configure channel, format and sample rate to
enable audio over HDMI.
Change-Id: Ieef8a2658f9730a9268041ac93ea3958489f2eae
Signed-off-by: Shiv Maliyappanahalli <smaliyap@codeaurora.org>
-rwxr-xr-x | sound/soc/codecs/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/msm/msmcobalt.c | 226 |
2 files changed, 196 insertions, 32 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 913bc0e06098..2963d00ea6e5 100755 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -967,7 +967,7 @@ config SND_SOC_MSM_STUB config SND_SOC_MSM_HDMI_CODEC_RX bool "HDMI Audio Playback" - depends on FB_MSM_MDSS_HDMI_PANEL && (SND_SOC_APQ8084 || SND_SOC_MSM8994 || SND_SOC_MSM8996) + depends on FB_MSM_MDSS_HDMI_PANEL && (SND_SOC_APQ8084 || SND_SOC_MSM8994 || SND_SOC_MSM8996 || SND_SOC_MSMCOBALT) help HDMI audio drivers should be built only if the platform supports hdmi panel. diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c index e4ad523bacb7..68bde8b9bb6e 100644 --- a/sound/soc/msm/msmcobalt.c +++ b/sound/soc/msm/msmcobalt.c @@ -89,13 +89,7 @@ enum { SLIM_TX_MAX, }; -struct slim_ch_config { - u32 sample_rate; - u32 bit_format; - u32 channels; -}; - -struct usb_be_config { +struct dev_config { u32 sample_rate; u32 bit_format; u32 channels; @@ -122,7 +116,7 @@ struct msm_asoc_wcd93xx_codec { }; /* Default configuration of slimbus channels */ -static struct slim_ch_config slim_rx_cfg[] = { +static struct dev_config slim_rx_cfg[] = { [SLIM_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, [SLIM_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, [SLIM_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, @@ -133,7 +127,7 @@ static struct slim_ch_config slim_rx_cfg[] = { [SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, }; -static struct slim_ch_config slim_tx_cfg[] = { +static struct dev_config slim_tx_cfg[] = { [SLIM_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, [SLIM_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, [SLIM_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, @@ -145,18 +139,24 @@ static struct slim_ch_config slim_tx_cfg[] = { [SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, }; -static struct usb_be_config usb_rx_cfg = { +static struct dev_config usb_rx_cfg = { .sample_rate = SAMPLING_RATE_48KHZ, .bit_format = SNDRV_PCM_FORMAT_S16_LE, .channels = 2, }; -static struct usb_be_config usb_tx_cfg = { +static struct dev_config usb_tx_cfg = { .sample_rate = SAMPLING_RATE_48KHZ, .bit_format = SNDRV_PCM_FORMAT_S16_LE, .channels = 1, }; +static struct dev_config hdmi_rx_cfg = { + .sample_rate = SAMPLING_RATE_48KHZ, + .bit_format = SNDRV_PCM_FORMAT_S16_LE, + .channels = 2, +}; + static int msm_vi_feed_tx_ch = 2; static const char *const slim_rx_ch_text[] = {"One", "Two"}; static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four", @@ -169,10 +169,14 @@ static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_96", "KHZ_192"}; static char const *bt_sco_sample_rate_text[] = {"KHZ_8", "KHZ_16"}; static const char *const usb_ch_text[] = {"One", "Two"}; +static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five", + "Six", "Seven", "Eight"}; static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025", "KHZ_16", "KHZ_22P05", "KHZ_32", "KHZ_44P1", "KHZ_48", "KHZ_96", "KHZ_192"}; +static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96", + "KHZ_192"}; static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_chs, slim_tx_ch_text); @@ -182,12 +186,14 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_chs, hdmi_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text); @@ -195,6 +201,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(bt_sco_sample_rate, bt_sco_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_sample_rate, hdmi_rx_sample_rate_text); static struct platform_device *spdev; @@ -914,6 +921,130 @@ static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol, return rc; } +static int hdmi_rx_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + switch (hdmi_rx_cfg.bit_format) { + case SNDRV_PCM_FORMAT_S24_3LE: + ucontrol->value.integer.value[0] = 2; + break; + + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + + pr_debug("%s: hdmi_rx_cfg = %d, ucontrol value = %ld\n", + __func__, hdmi_rx_cfg.bit_format, + ucontrol->value.integer.value[0]); + + return 0; +} + +static int hdmi_rx_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 2: + hdmi_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE; + break; + case 1: + hdmi_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + hdmi_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("%s: hdmi_rx_cfg.bit_format = %d, ucontrol value = %ld\n", + __func__, hdmi_rx_cfg.bit_format, + ucontrol->value.integer.value[0]); + + return 0; +} + +static int hdmi_rx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: hdmi_rx_cfg.channels = %d\n", __func__, + hdmi_rx_cfg.channels); + ucontrol->value.integer.value[0] = hdmi_rx_cfg.channels - 2; + + return 0; +} + +static int hdmi_rx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + hdmi_rx_cfg.channels = ucontrol->value.integer.value[0] + 2; + if (hdmi_rx_cfg.channels > 8) { + pr_err("%s: channels %d exceeded 8.Limiting to max chs-8\n", + __func__, hdmi_rx_cfg.channels); + hdmi_rx_cfg.channels = 8; + } + pr_debug("%s: hdmi_rx_cfg.channels = %d\n", __func__, + hdmi_rx_cfg.channels); + + return 1; +} + +static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int sample_rate_val = 0; + + switch (hdmi_rx_cfg.sample_rate) { + case SAMPLING_RATE_192KHZ: + sample_rate_val = 2; + break; + + case SAMPLING_RATE_96KHZ: + sample_rate_val = 1; + break; + + case SAMPLING_RATE_48KHZ: + default: + sample_rate_val = 0; + break; + } + + ucontrol->value.integer.value[0] = sample_rate_val; + pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__, + hdmi_rx_cfg.sample_rate); + + return 0; +} + +static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: ucontrol value = %ld\n", __func__, + ucontrol->value.integer.value[0]); + + switch (ucontrol->value.integer.value[0]) { + case 2: + hdmi_rx_cfg.sample_rate = SAMPLING_RATE_192KHZ; + break; + case 1: + hdmi_rx_cfg.sample_rate = SAMPLING_RATE_96KHZ; + break; + case 0: + default: + hdmi_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ; + } + + pr_debug("%s: hdmi_rx_cfg.sample_rate = %d\n", __func__, + hdmi_rx_cfg.sample_rate); + + return 0; +} + static const struct snd_kcontrol_new msm_snd_controls[] = { SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs, msm_slim_rx_ch_get, msm_slim_rx_ch_put), @@ -931,6 +1062,8 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { usb_audio_rx_ch_get, usb_audio_rx_ch_put), SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs, usb_audio_tx_ch_get, usb_audio_tx_ch_put), + SOC_ENUM_EXT("HDMI_RX Channels", hdmi_rx_chs, + hdmi_rx_ch_get, hdmi_rx_ch_put), SOC_ENUM_EXT("SLIM_0_RX Format", slim_0_rx_format, slim_rx_bit_format_get, slim_rx_bit_format_put), SOC_ENUM_EXT("SLIM_5_RX Format", slim_5_rx_format, @@ -943,6 +1076,8 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { usb_audio_rx_format_get, usb_audio_rx_format_put), SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format, usb_audio_tx_format_get, usb_audio_tx_format_put), + SOC_ENUM_EXT("HDMI_RX Bit Format", hdmi_rx_format, + hdmi_rx_format_get, hdmi_rx_format_put), SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate, slim_rx_sample_rate_get, slim_rx_sample_rate_put), SOC_ENUM_EXT("SLIM_0_TX SampleRate", slim_0_tx_sample_rate, @@ -960,6 +1095,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { SOC_ENUM_EXT("USB_AUDIO_TX SampleRate", usb_tx_sample_rate, usb_audio_tx_sample_rate_get, usb_audio_tx_sample_rate_put), + SOC_ENUM_EXT("HDMI_RX SampleRate", hdmi_rx_sample_rate, + hdmi_rx_sample_rate_get, + hdmi_rx_sample_rate_put), }; static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, @@ -1147,6 +1285,15 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = channels->max = usb_tx_cfg.channels; break; + case MSM_BACKEND_DAI_HDMI_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + hdmi_rx_cfg.bit_format); + if (channels->max < 2) + channels->min = channels->max = 2; + rate->min = rate->max = hdmi_rx_cfg.sample_rate; + channels->min = channels->max = hdmi_rx_cfg.channels; + break; + default: rate->min = rate->max = SAMPLING_RATE_48KHZ; break; @@ -2761,12 +2908,31 @@ static struct snd_soc_dai_link msm_wcn_be_dai_links[] = { }, }; +static struct snd_soc_dai_link hdmi_be_dai_link[] = { + /* HDMI BACK END DAI Link */ + { + .name = LPASS_BE_HDMI, + .stream_name = "HDMI Playback", + .cpu_dai_name = "msm-dai-q6-hdmi.8", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-hdmi-audio-codec-rx", + .codec_dai_name = "msm_hdmi_audio_codec_rx_dai", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_HDMI_RX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, +}; + static struct snd_soc_dai_link msm_tasha_dai_links[ ARRAY_SIZE(msm_common_dai_links) + ARRAY_SIZE(msm_tasha_fe_dai_links) + ARRAY_SIZE(msm_common_be_dai_links) + ARRAY_SIZE(msm_tasha_be_dai_links) + - ARRAY_SIZE(msm_wcn_be_dai_links)]; + ARRAY_SIZE(msm_wcn_be_dai_links) + + ARRAY_SIZE(hdmi_be_dai_link)]; static int msm_snd_card_late_probe(struct snd_soc_card *card) { @@ -3083,10 +3249,9 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) { struct snd_soc_card *card = NULL; struct snd_soc_dai_link *dailink; - int len_1, len_2, len_3, len_4; + int len_1, len_2, len_3; int total_links; const struct of_device_id *match; - bool use_wcn_btfm = false; match = of_match_node(msmcobalt_asoc_machine_of_match, dev->of_node); if (!match) { @@ -3095,26 +3260,12 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) return NULL; } - if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) { - use_wcn_btfm = true; - dev_dbg(dev, "%s(): WCN BTFM support present\n", __func__); - } else { - dev_dbg(dev, "%s(): No WCN BTFM support\n", __func__); - } - if (!strcmp(match->data, "tasha_codec")) { card = &snd_soc_card_tasha_msm; len_1 = ARRAY_SIZE(msm_common_dai_links); len_2 = len_1 + ARRAY_SIZE(msm_tasha_fe_dai_links); len_3 = len_2 + ARRAY_SIZE(msm_common_be_dai_links); - len_4 = len_3 + ARRAY_SIZE(msm_tasha_be_dai_links); - if (use_wcn_btfm) { - total_links = len_4 + - ARRAY_SIZE(msm_wcn_be_dai_links); - } else { - total_links = len_4; - } - + total_links = len_3 + ARRAY_SIZE(msm_tasha_be_dai_links); memcpy(msm_tasha_dai_links, msm_common_dai_links, sizeof(msm_common_dai_links)); @@ -3127,10 +3278,23 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) memcpy(msm_tasha_dai_links + len_3, msm_tasha_be_dai_links, sizeof(msm_tasha_be_dai_links)); - if (use_wcn_btfm) - memcpy(msm_tasha_dai_links + len_4, + + if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) { + dev_dbg(dev, "%s(): WCN BTFM support present\n", + __func__); + memcpy(msm_tasha_dai_links + total_links, msm_wcn_be_dai_links, sizeof(msm_wcn_be_dai_links)); + total_links += ARRAY_SIZE(msm_wcn_be_dai_links); + } + + if (of_property_read_bool(dev->of_node, "qcom,hdmi-audio-rx")) { + dev_dbg(dev, "%s(): HDMI support present\n", __func__); + memcpy(msm_tasha_dai_links + total_links, + hdmi_be_dai_link, + sizeof(hdmi_be_dai_link)); + total_links += ARRAY_SIZE(hdmi_be_dai_link); + } dailink = msm_tasha_dai_links; } else if (!strcmp(match->data, "stub_codec")) { |