[STLinux Kernel] [PATCH v2 4/4] ASoC: hdmi-codec: add channel mapping control

Arnaud Pouliquen arnaud.pouliquen at st.com
Mon Dec 19 11:07:03 UTC 2016


I detected 2 issues in this version, details below.

V3 is following.
Sorry for the inconvenience...

Regards
Arnaud

On 12/14/2016 04:16 PM, Arnaud Pouliquen wrote:
> +static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc)
> +{
> +	int i;
> +	const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {
> +		[0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR,
> +		[4] = RC, [5] = FLC | FRC, [6] = RLC | RRC,
> +	};
> +	unsigned long spk_mask;
Missing initialization that generates warning during compilation
> +
> +	for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) {
> +		if (spk_alloc & (1 << i))
> +			spk_mask |= hdmi_codec_eld_spk_alloc_bits[i];
> +	}
> +
> +	return spk_mask;
> +}
> +
> +/* From speaker bit mask to ALSA API channel position */
> +static int snd_hdac_spk_to_chmap(int spk)
> +{
> +	const struct hdmi_codec_channel_map_table *t = hdmi_codec_map_table;
> +
> +	for (; t->map; t++) {
> +		if (t->spk_mask == spk)
> +			return t->map;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * hdmi_codec_cea_init_channel_alloc:
> + * Compute derived values in hdmi_codec_channel_alloc[].
> + * spk_na_mask is used to store unused channels in mid of the channel
> + * allocations. These particular channels are then considered as active channels
> + * For instance:
> + *    CA_ID 0x02: CA =  (FL, FR, 0, FC) => spk_na_mask = 0x04, channels = 4
> + *    CA_ID 0x04: CA =  (FL, FR, 0, 0, RC) => spk_na_mask = 0x03C, channels = 5
> + */
> +static void hdmi_codec_cea_init_channel_alloc(void)
> +{
> +	int i, j, k, last;
> +	struct hdmi_codec_cea_spk_alloc *p;
> +
> +	/* Test if not already done by another instance */
> +	if (hdmi_codec_channel_alloc[0].channels)
> +		return;
> +
> +	for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++) {
> +		p = hdmi_codec_channel_alloc + i;
> +		p->spks_mask = 0;
> +		p->spk_na_mask = 0;
> +		last = HDMI_MAX_SPEAKERS;
> +		for (j = 0, k = 7; j < HDMI_MAX_SPEAKERS; j++, k--) {
> +			if (p->speakers[j]) {
> +				p->spks_mask |= p->speakers[j];
> +				if (last == HDMI_MAX_SPEAKERS)
> +					last = j;
> +			} else if (last != HDMI_MAX_SPEAKERS) {
> +				p->spk_na_mask |= 1 << k;
> +			}
> +		}
> +		p->channels = 8 - last;
> +	}
> +}
> +
> +static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp,
> +					     unsigned char channels)
> +{
> +	int i;
> +	u8 spk_alloc;
> +	unsigned long spk_mask;
> +	struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc;
> +
> +	spk_alloc = drm_eld_get_spk_alloc(hcp->eld);
> +	spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
> +
> +	for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) {
> +		if (cap->channels != channels)
> +			continue;
> +		if (!(cap->spks_mask == (spk_mask & cap->spks_mask)))
> +			continue;
> +		return i;
> +	}
> +
If HDMI cable not plugged, ELD is empty. In this case this function
returns an error. For backward compatible, it should not return an error
but a default allocation that should be stereo.

> +	return -EINVAL;
> +}
> +
> +static void hdmi_cea_alloc_to_tlv_spks(struct hdmi_codec_cea_spk_alloc *cap,
> +				       unsigned char *chmap)
> +{
> +	int count = 0;
> +	int c, spk;
> +
> +	/* Detect unused channels in cea caps, tag them as N/A channel in TLV */
> +	for (c = 0; c < HDMI_MAX_SPEAKERS; c++) {
> +		spk = cap->speakers[7 - c];
> +		if (cap->spk_na_mask & BIT(c))
> +			chmap[count++] = SNDRV_CHMAP_NA;
> +		else
> +			chmap[count++] = snd_hdac_spk_to_chmap(spk);
> +	}
> +}
> +
> +static void hdmi_cea_alloc_to_tlv_chmap(struct hdmi_codec_priv *hcp,
> +					struct hdmi_codec_cea_spk_alloc *cap)
> +{
> +	unsigned int chs, count = 0;
> +	struct snd_pcm_chmap *info = hcp->chmap_info;
> +	struct snd_pcm_chmap_elem *chmap = info->chmap;
> +	unsigned long max_chs = info->max_channels;
> +	int num_ca = ARRAY_SIZE(hdmi_codec_channel_alloc);
> +	int spk_alloc, spk_mask;
> +
> +	spk_alloc = drm_eld_get_spk_alloc(hcp->eld);
> +	spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
> +
> +	for (chs = 2; chs <= max_chs; chs++) {
> +		int i;
> +		struct hdmi_codec_cea_spk_alloc *cap;
> +
> +		cap = hdmi_codec_channel_alloc;
> +		for (i = 0; i < num_ca; i++, cap++) {
> +			if (cap->channels != chs)
> +				continue;
> +
> +			if (!(cap->spks_mask == (spk_mask & cap->spks_mask)))
> +				continue;
> +
> +			chmap[count].channels = cap->channels;
> +			hdmi_cea_alloc_to_tlv_spks(cap, chmap[count].map);
> +			count++;
> +		}
> +	}
> +
> +	/* Force last one to 0 to indicate end of available allocations */
> +	chmap[count].channels = 0;
> +}
> +


More information about the dri-devel mailing list