[alsa-devel] [RFC v2 1/6] drm/mediatek: hdmi: Add audio interface to the hdmi-codec driver

Philipp Zabel p.zabel at pengutronix.de
Tue Jan 5 15:56:36 CET 2016


Hi Russell,

Am Montag, den 04.01.2016, 22:29 +0000 schrieb Russell King - ARM Linux:
> On Mon, Jan 04, 2016 at 08:09:06PM +0100, Philipp Zabel wrote:
> > Add the interface needed by Jyri's generic hdmi-codec driver [1] to start
> > or stop audio playback and to retrieve ELD (EDID like data) to limit the
> > supported audio formats to the HDMI sink capabilities.
> 
> Some of this makes me rather suspicious.

Thanks for being suspicious, then.

> > +	switch (params->sample_rate) {
> > +	case 32000:
> > +		hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_32000;
> > +		hdmi_params.iec_frame_fs = HDMI_IEC_32K;
> > +		/* channel status byte 3: fs and clock accuracy */
> > +		hdmi_params.hdmi_l_channel_state[3] = 0x3;
> > +		break;
> > +	case 44100:
> > +		hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_44100;
> > +		hdmi_params.iec_frame_fs = HDMI_IEC_44K;
> > +		/* channel status byte 3: fs and clock accuracy */
> > +		hdmi_params.hdmi_l_channel_state[3] = 0;
> > +		break;
> > +	case 48000:
> > +		hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
> > +		hdmi_params.iec_frame_fs = HDMI_IEC_48K;
> > +		/* channel status byte 3: fs and clock accuracy */
> > +		hdmi_params.hdmi_l_channel_state[3] = 0x2;
> > +		break;
> > +	case 88200:
> > +		hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_88200;
> > +		hdmi_params.iec_frame_fs = HDMI_IEC_88K;
> > +		/* channel status byte 3: fs and clock accuracy */
> > +		hdmi_params.hdmi_l_channel_state[3] = 0x8;
> > +		break;
> > +	case 96000:
> > +		hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_96000;
> > +		hdmi_params.iec_frame_fs = HDMI_IEC_96K;
> > +		/* channel status byte 3: fs and clock accuracy */
> > +		hdmi_params.hdmi_l_channel_state[3] = 0xa;
> > +		break;
> > +	case 176400:
> > +		hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_176400;
> > +		hdmi_params.iec_frame_fs = HDMI_IEC_176K;
> > +		/* channel status byte 3: fs and clock accuracy */
> > +		hdmi_params.hdmi_l_channel_state[3] = 0xc;
> > +		break;
> > +	case 192000:
> > +		hdmi_params.aud_hdmi_fs = HDMI_AUDIO_SAMPLE_FREQUENCY_192000;
> > +		hdmi_params.iec_frame_fs = HDMI_IEC_192K;
> > +		/* channel status byte 3: fs and clock accuracy */
> > +		hdmi_params.hdmi_l_channel_state[3] = 0xe;
> 
> For exmaple, all the above.  The HDMI standards say that the audio info
> frame "shall" always set the sample frequency to "refer to stream" for
> L-PCM and IEC61937 compressed audio.  The above looks like it violates
> the HDMI specification as I'm willing to bet that hdmi_params.aud_hdmi_fs
> gets passed over into the audio info frame.
>
> Many of the fields in the audio info frame are supposed to be set as
> "refer to stream".  I'd suggest ensuring that you're compliant with
> these.

The audio inforame is generated using

        struct hdmi_audio_infoframe frame;
        hdmi_audio_infoframe_init(&frame);
        frame.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
        frame.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
        frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
        frame.channels =
            mtk_hdmi_aud_get_chnl_count(
            hdmi->aud_param.aud_input_chan_type);
        hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));

later. aud_hdmi_fs/iec_frame_fs are used to select the values written to
the N/CTS register. Instead of those I could just pass the sample_rate
down to the lower layers.

> The second thing is that "hdmi_params.hdmi_l_channel_state" looks like
> it's the IEC958 bytes.  These must be correct for some of the higher
> end HDMI receivers (eg, Yamaha RX-V677) to correctly process the audio.

I think you are right. These values are written to 24-byte register sets
"L_STATUS" and "R_STATUS" (padded with zeroes) as well as to the 5-byte
register set "I2S_C_STA" for the first five bytes.

> > +		break;
> > +	default:
> > +		dev_err(hdmi->dev, "rate[%d] not supported!\n",
> > +			params->sample_rate);
> > +		return -EINVAL;
> > +	}
> > +
> > +	switch (daifmt->fmt) {
> > +	case HDMI_I2S:
> > +		hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
> > +		hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
> > +		hdmi_params.aud_input_type = HDMI_AUD_INPUT_I2S;
> > +		hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
> > +		hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS;
> > +		break;
> > +	default:
> > +		dev_err(hdmi->dev, "%s: Invalid format %d\n", __func__,
> > +			daifmt->fmt);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* channel status */
> > +	/* byte 0: no copyright is asserted, mode 0 */
> > +	hdmi_params.hdmi_l_channel_state[0] = 1 << 2;
> > +	/* byte 1: category code */
> > +	hdmi_params.hdmi_l_channel_state[1] = 0;
> > +	/* byte 2: source/channel number don't take into account */
> > +	hdmi_params.hdmi_l_channel_state[2] = 0;
> > +	/* byte 4: word length 16bits */
> > +	hdmi_params.hdmi_l_channel_state[4] = 0x2;
> > +	memcpy(hdmi_params.hdmi_r_channel_state,
> > +	       hdmi_params.hdmi_l_channel_state,
> > +	       sizeof(hdmi_params.hdmi_l_channel_state));
> 
> Hmm, yes, it is the IEC958 channel status bytes.  We have a helper
> for this - snd_pcm_create_iec958_consumer().

hdmi-codec already calls snd_pcm_create_iec958_consumer and provides the
result via params->iec.state, so I'll try to just use that.

regards
Philipp



More information about the Alsa-devel mailing list