@@ -92,6 +92,7 @@ struct hdmi_codec_pdata {
const struct hdmi_codec_ops *ops;
uint i2s:1;
uint spdif:1;
+ uint iec_ctl:1;
int max_i2s_channels;
};
@@ -32,6 +32,7 @@ struct hdmi_codec_priv {
struct snd_pcm_substream *current_stream;
struct snd_pcm_hw_constraint_list ratec;
uint8_t eld[MAX_ELD_BYTES];
+ struct snd_aes_iec958 iec;
};
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -122,26 +123,29 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
- struct hdmi_codec_params hp = {
- .iec = {
- .status = { 0 },
- .subcode = { 0 },
- .pad = 0,
- .dig_subframe = { 0 },
- }
- };
+ struct hdmi_codec_params hp;
int ret;
dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
params_width(params), params_rate(params),
params_channels(params));
- ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status,
- sizeof(hp.iec.status));
- if (ret < 0) {
- dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
- ret);
- return ret;
+ mutex_lock(&hcp->current_stream_lock);
+ hp.iec = hcp->iec;
+ mutex_unlock(&hcp->current_stream_lock);
+
+ if (!hcp->hcd.iec_ctl) {
+ /*
+ * only PCM format supported
+ *channel status set according to runtime parameters
+ */
+ ret = snd_pcm_create_iec958_consumer_hw_params(params,
+ hp.iec.status, sizeof(hp.iec.status));
+ if (ret < 0) {
+ dev_err(dai->dev, "Creating IEC958 status failed %d\n",
+ ret);
+ return ret;
+ }
}
ret = hdmi_codec_new_stream(substream, dai);
@@ -248,6 +252,27 @@ static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute)
return 0;
}
+static int hdmi_codec_dai_probe(struct snd_soc_dai *dai)
+{
+ struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+ struct snd_pcm_iec958_params *iec958_params;
+ const struct snd_kcontrol_new *ctrl;
+
+ if (!hcp->hcd.iec_ctl)
+ return 0;
+
+ iec958_params = devm_kzalloc(dai->dev, sizeof(*iec958_params),
+ GFP_KERNEL);
+ if (!iec958_params)
+ return -ENOMEM;
+
+ iec958_params->iec = &hcp->iec;
+ iec958_params->mutex = &hcp->current_stream_lock;
+
+ ctrl = snd_pcm_iec958_ctl_new(SNDRV_PCM_STREAM_PLAYBACK);
+ return snd_soc_add_dai_pcm_controls(dai, ctrl, 1, iec958_params);
+}
+
static const struct snd_soc_dai_ops hdmi_dai_ops = {
.startup = hdmi_codec_startup,
.shutdown = hdmi_codec_shutdown,
@@ -293,6 +318,7 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = {
.sig_bits = 24,
},
.ops = &hdmi_dai_ops,
+ .probe = hdmi_codec_dai_probe,
};
static const struct snd_soc_dai_driver hdmi_spdif_dai = {
Create 'IEC958 Playback Default' controls to support IEC61937 formats. the use of the alsa control is optional, using 'iec_ctl' flag. Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> --- include/sound/hdmi-codec.h | 1 + sound/soc/codecs/hdmi-codec.c | 54 ++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 14 deletions(-)