1
0
Fork 0

MLK-23642-2: ASoC: hdmi-codec: Add iec958 kcontrol

Add iec958 controls, then user can set the AES from user space.
The command is "iecset", which is in alsa-utils.

For HBR test, we need do below steps
1. Generate iec61937 mat stream by ffmpeg.
   ffmpeg -i input.mlp -acodec copy -f spdif output.spd

2. Add iec60958 header by iec958 plugin in alsa-lib

<confdir:pcm/iec958.conf>

IMX-CDNHDMI.pcm.iec958.0 {
	@args [ CARD AES0 AES1 AES2 AES3 ]
	@args.CARD {
		type string
	}
	@args.AES0 {
		type integer
	}
	@args.AES1 {
		type integer
	}
	@args.AES2 {
		type integer
	}
	@args.AES3 {
		type integer
	}
	type iec958
	slave {
		format IEC958_SUBFRAME_LE
		pcm {
			type file
			slave.pcm null
			file "output.spd.iec958"
			format "raw"
		}
	}
	status [ $AES0 $AES1 $AES2 $AES3 ]
	preamble.z 0x1
	preamble.x 0x0
	preamble.y 0x0
}
aplay -Diec958:3,AES0=0x06,AES1=0x80,AES2=0x02,AES3=0x09 -r 192000 -c 2 -f S16_LE output.spd

3. Enable non-linear pcm.
   iecset -c 3 audio off

4. aplay -Dcdnhdmi8ch -r 192000 -c 8 -f S32_LE output.spd.iec958
pcm.cdnhdmi8ch {
        type dshare
        slave {
                pcm "hw:3,0"
                channels 8
                rate 192000
                format S32_LE
        }
        ipc_key 5144458
        bindings.0 0
        bindings.1 4
        bindings.2 1
        bindings.3 5
        bindings.4 2
        bindings.5 6
        bindings.6 3
        bindings.7 7
}

5. Test is finished, disable non-linear pcm
   iecset -c 3 audio on

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Shengjiu Wang 2020-04-29 17:38:44 +08:00
parent 81875f6f91
commit 326442c327
1 changed files with 63 additions and 0 deletions

View File

@ -277,6 +277,7 @@ struct hdmi_codec_priv {
unsigned long busy;
struct snd_soc_jack *jack;
unsigned int jack_status;
struct snd_aes_iec958 iec;
};
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@ -385,6 +386,51 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
return 0;
}
/*
* ALSA iec958 controls
*/
static int hdmi_codec_iec958_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
static int hdmi_codec_iec958_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(comp);
int i;
for (i = 0; i < 24; i++)
ucontrol->value.iec958.status[i] = hcp->iec.status[i];
return 0;
}
static int hdmi_codec_iec958_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(comp);
int i;
for (i = 0; i < 24; i++)
hcp->iec.status[i] = ucontrol->value.iec958.status[i];
return 0;
}
static const struct snd_kcontrol_new hdmi_codec_controls = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
.info = hdmi_codec_iec958_info,
.get = hdmi_codec_iec958_get,
.put = hdmi_codec_iec958_put,
};
static int hdmi_codec_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@ -464,6 +510,15 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
return ret;
}
if (hcp->iec.status[0] || hcp->iec.status[1] || hcp->iec.status[2] ||
hcp->iec.status[3] || hcp->iec.status[4]) {
hp.iec.status[0] = hcp->iec.status[0];
hp.iec.status[1] = hcp->iec.status[1];
hp.iec.status[2] = hcp->iec.status[2];
hp.iec.status[3] = hcp->iec.status[3];
hp.iec.status[4] = hcp->iec.status[4];
}
hdmi_audio_infoframe_init(&hp.cea);
hp.cea.channels = params_channels(params);
hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
@ -635,6 +690,14 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
kctl = snd_ctl_new1(&hdmi_codec_controls, dai->component);
if (!kctl)
return -ENOMEM;
ret = snd_ctl_add(rtd->card->snd_card, kctl);
if (ret < 0)
return ret;
/* add ELD ctl with the device number corresponding to the PCM stream */
kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component);
if (!kctl)