Merge "ASoC: msm: Add 24-bit playback support over HDMI"
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 50a0113..5697941 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -44,6 +44,7 @@
 #define BTSCO_RATE_16KHZ 16000
 
 static int slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
+static int hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
 
 #define SAMPLING_RATE_48KHZ 48000
 #define SAMPLING_RATE_96KHZ 96000
@@ -733,6 +734,46 @@
 	return 0;
 }
 
+static int hdmi_rx_bit_format_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+
+	switch (hdmi_rx_bit_format) {
+	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_bit_format = %d, ucontrol value = %ld\n",
+			 __func__, hdmi_rx_bit_format,
+			ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int hdmi_rx_bit_format_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
+			 __func__, hdmi_rx_bit_format,
+			ucontrol->value.integer.value[0]);
+	return 0;
+}
+
 static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -840,6 +881,8 @@
 	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
 			channels->min, channels->max);
 
+	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				hdmi_rx_bit_format);
 	if (channels->max < 2)
 		channels->min = channels->max = 2;
 	rate->min = rate->max = 48000;
@@ -1067,6 +1110,8 @@
 			slim0_rx_bit_format_get, slim0_rx_bit_format_put),
 	SOC_ENUM_EXT("SLIM_0_RX SampleRate", msm_snd_enum[5],
 			slim0_rx_sample_rate_get, slim0_rx_sample_rate_put),
+	SOC_ENUM_EXT("HDMI_RX Bit Format", msm_snd_enum[4],
+			hdmi_rx_bit_format_get, hdmi_rx_bit_format_put),
 };
 
 static bool msm8974_swap_gnd_mic(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 329d293..16df886 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -23,6 +23,7 @@
 #include <sound/apr_audio-v2.h>
 #include <sound/q6afe-v2.h>
 #include <sound/msm-dai-q6-v2.h>
+#include <sound/pcm_params.h>
 
 #define HDMI_RX_CA_MAX 0x32
 
@@ -119,7 +120,14 @@
 	dai_data->port_config.hdmi_multi_ch.reserved = 0;
 	dai_data->port_config.hdmi_multi_ch.hdmi_cfg_minor_version = 1;
 	dai_data->port_config.hdmi_multi_ch.sample_rate = dai_data->rate;
-	dai_data->port_config.hdmi_multi_ch.bit_width = 16;
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		dai_data->port_config.hdmi_multi_ch.bit_width = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		dai_data->port_config.hdmi_multi_ch.bit_width = 24;
+		break;
+	}
 
 	switch (dai_data->channels) {
 	case 2:
@@ -257,7 +265,7 @@
 static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 		.channels_min = 2,
 		.channels_max = 8,
 		.rate_max =     48000,