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;
> +}
> +

Reply via email to