aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSubhransu S. Prusty <subhransu.s.prusty@intel.com>2016-02-11 21:16:02 -0500
committerMark Brown <broonie@kernel.org>2016-02-15 15:11:09 -0500
commit2428bca305e082885e08e7f3399db616daf3a51a (patch)
treead8c3854df15bb582876336244d10b38b4449301
parentb8a54545b00cbf2aff743578c5c69aafdcde1d64 (diff)
ASoC: hdac_hdmi: Apply constraints based on ELD
Uses the drm ELD core framework to apply rate and channel Also compute the format to be set based on ELD. Even though the channel constraint is based on ELD, infoframe is set with stereo only. Multichannel support will be added later. Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/Kconfig1
-rw-r--r--sound/soc/codecs/hdac_hdmi.c51
2 files changed, 49 insertions, 3 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 50693c867e71..8c86239cc3f2 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -490,6 +490,7 @@ config SND_SOC_GTM601
490config SND_SOC_HDAC_HDMI 490config SND_SOC_HDAC_HDMI
491 tristate 491 tristate
492 select SND_HDA_EXT_CORE 492 select SND_HDA_EXT_CORE
493 select SND_PCM_ELD
493 select HDMI 494 select HDMI
494 495
495config SND_SOC_ICS43432 496config SND_SOC_ICS43432
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index fff225d6539c..d22fa6b66c80 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -22,10 +22,12 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/pm_runtime.h> 23#include <linux/pm_runtime.h>
24#include <linux/hdmi.h> 24#include <linux/hdmi.h>
25#include <drm/drm_edid.h>
25#include <sound/pcm_params.h> 26#include <sound/pcm_params.h>
26#include <sound/soc.h> 27#include <sound/soc.h>
27#include <sound/hdaudio_ext.h> 28#include <sound/hdaudio_ext.h>
28#include <sound/hda_i915.h> 29#include <sound/hda_i915.h>
30#include <sound/pcm_drm_eld.h>
29#include "../../hda/local.h" 31#include "../../hda/local.h"
30 32
31#define AMP_OUT_MUTE 0xb080 33#define AMP_OUT_MUTE 0xb080
@@ -90,6 +92,45 @@ static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
90 return to_ehdac_device(hdac); 92 return to_ehdac_device(hdac);
91} 93}
92 94
95static unsigned int sad_format(const u8 *sad)
96{
97 return ((sad[0] >> 0x3) & 0x1f);
98}
99
100static unsigned int sad_sample_bits_lpcm(const u8 *sad)
101{
102 return (sad[2] & 7);
103}
104
105static int hdac_hdmi_eld_limit_formats(struct snd_pcm_runtime *runtime,
106 void *eld)
107{
108 u64 formats = SNDRV_PCM_FMTBIT_S16;
109 int i;
110 const u8 *sad, *eld_buf = eld;
111
112 sad = drm_eld_sad(eld_buf);
113 if (!sad)
114 goto format_constraint;
115
116 for (i = drm_eld_sad_count(eld_buf); i > 0; i--, sad += 3) {
117 if (sad_format(sad) == 1) { /* AUDIO_CODING_TYPE_LPCM */
118
119 /*
120 * the controller support 20 and 24 bits in 32 bit
121 * container so we set S32
122 */
123 if (sad_sample_bits_lpcm(sad) & 0x6)
124 formats |= SNDRV_PCM_FMTBIT_S32;
125 }
126 }
127
128format_constraint:
129 return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
130 formats);
131
132}
133
93 /* HDMI ELD routines */ 134 /* HDMI ELD routines */
94static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec, 135static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec,
95 hda_nid_t nid, int byte_index) 136 hda_nid_t nid, int byte_index)
@@ -334,6 +375,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
334 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); 375 struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
335 struct hdac_hdmi_priv *hdmi = hdac->private_data; 376 struct hdac_hdmi_priv *hdmi = hdac->private_data;
336 struct hdac_hdmi_dai_pin_map *dai_map; 377 struct hdac_hdmi_dai_pin_map *dai_map;
378 int ret;
337 379
338 if (dai->id > 0) { 380 if (dai->id > 0) {
339 dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n"); 381 dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n");
@@ -358,10 +400,13 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
358 snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0, 400 snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
359 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 401 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
360 402
361 snd_pcm_hw_constraint_step(substream->runtime, 0, 403 ret = hdac_hdmi_eld_limit_formats(substream->runtime,
362 SNDRV_PCM_HW_PARAM_CHANNELS, 2); 404 dai_map->pin->eld.eld_buffer);
405 if (ret < 0)
406 return ret;
363 407
364 return 0; 408 return snd_pcm_hw_constraint_eld(substream->runtime,
409 dai_map->pin->eld.eld_buffer);
365} 410}
366 411
367static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, 412static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,