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; > +} > + _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel