On Wed, 05 Jul 2017 10:15:35 +0200,
Kuninori Morimoto wrote:
> 
> 
> From: Kuninori Morimoto <[email protected]>
> 
> Current hdmi-codec driver is using hdmi_controls for "ELD" control.
> But, hdmi-codec driver might be used from many HDMIs. In such case,
> they will use same "ELD" name and kernel will indicate below error.
> 
>       xxx: control x:x:x:ELD:x is already present
> 
> hdmi_controls will be registered in soc_probe_component(), and we can
> replace it by component driver probe function.
> 
> This patch registers current hdmi_controls in new hdmi_probe().
> If hdmi-codec is used from only 1 device, it will use "ELD" as control name
> (We can keep compatibility).
> If hdmi-codec is used from many devices, it will use "ELD.x" as control name.

The de facto standard way as HD-audio does is to pass the device
number of each ELD control as same as the corresponding PCM stream
number.


thanks,

Takashi

> Signed-off-by: Kuninori Morimoto <[email protected]>
> ---
>  sound/soc/codecs/hdmi-codec.c | 60 
> +++++++++++++++++++++++++++++++++----------
>  1 file changed, 46 insertions(+), 14 deletions(-)
> 
> diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
> index 22ed0dc..5835a90 100644
> --- a/sound/soc/codecs/hdmi-codec.c
> +++ b/sound/soc/codecs/hdmi-codec.c
> @@ -276,6 +276,7 @@ struct hdmi_codec_cea_spk_alloc {
>         .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
>  };
>  
> +#define ELD_NAME_SIZE        8
>  struct hdmi_codec_priv {
>       struct hdmi_codec_pdata hcd;
>       struct snd_soc_dai_driver *daidrv;
> @@ -284,7 +285,10 @@ struct hdmi_codec_priv {
>       struct snd_pcm_substream *current_stream;
>       uint8_t eld[MAX_ELD_BYTES];
>       struct snd_pcm_chmap *chmap_info;
> +     struct snd_kcontrol_new control;
>       unsigned int chmap_idx;
> +     int id;
> +     char eld_name[ELD_NAME_SIZE];
>  };
>  
>  static const struct snd_soc_dapm_widget hdmi_widgets[] = {
> @@ -399,18 +403,6 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol 
> *kcontrol,
>       return 0;
>  }
>  
> -
> -static const struct snd_kcontrol_new hdmi_controls[] = {
> -     {
> -             .access = SNDRV_CTL_ELEM_ACCESS_READ |
> -                       SNDRV_CTL_ELEM_ACCESS_VOLATILE,
> -             .iface = SNDRV_CTL_ELEM_IFACE_PCM,
> -             .name = "ELD",
> -             .info = hdmi_eld_ctl_info,
> -             .get = hdmi_eld_ctl_get,
> -     },
> -};
> -
>  static int hdmi_codec_new_stream(struct snd_pcm_substream *substream,
>                                struct snd_soc_dai *dai)
>  {
> @@ -718,6 +710,45 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime 
> *rtd,
>       .pcm_new = hdmi_codec_pcm_new,
>  };
>  
> +static int hdmi_last_id = 0;
> +static int hdmi_probe(struct snd_soc_component *component)
> +{
> +     struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
> +     static struct snd_soc_component *component_1st = NULL;
> +     char *name = "ELD";
> +
> +     /*
> +      * It will use "ELD"   if hdmi_codec was used from only 1 device.
> +      * It will use "ELD.x" if hdmi_codec was used from many devices.
> +      * Then, first "ELD" will be replaced to "ELD.0"
> +      */
> +     snprintf(hcp->eld_name, ELD_NAME_SIZE, "ELD.%d", hcp->id);
> +
> +     if (hcp->id == 0)
> +             component_1st = component;
> +
> +     if (hdmi_last_id > 1) {
> +             name = hcp->eld_name;
> +
> +             if (component_1st) {
> +                     struct hdmi_codec_priv *hcp_1st;
> +
> +                     /* replaced 1st "ELD" to "ELD.0" */
> +                     hcp_1st = snd_soc_component_get_drvdata(component_1st);
> +                     hcp_1st->control.name = hcp_1st->eld_name;
> +             }
> +     }
> +
> +     hcp->control.access     = SNDRV_CTL_ELEM_ACCESS_READ |
> +                               SNDRV_CTL_ELEM_ACCESS_VOLATILE;
> +     hcp->control.iface      = SNDRV_CTL_ELEM_IFACE_PCM;
> +     hcp->control.name       = name;
> +     hcp->control.info       = hdmi_eld_ctl_info;
> +     hcp->control.get        = hdmi_eld_ctl_get;
> +
> +     return snd_soc_add_component_controls(component, &hcp->control, 1);
> +}
> +
>  static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
>                                struct device_node *endpoint)
>  {
> @@ -732,8 +763,7 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component 
> *component,
>  
>  static struct snd_soc_codec_driver hdmi_codec = {
>       .component_driver = {
> -             .controls               = hdmi_controls,
> -             .num_controls           = ARRAY_SIZE(hdmi_controls),
> +             .probe                  = hdmi_probe,
>               .dapm_widgets           = hdmi_widgets,
>               .num_dapm_widgets       = ARRAY_SIZE(hdmi_widgets),
>               .dapm_routes            = hdmi_routes,
> @@ -768,6 +798,7 @@ static int hdmi_codec_probe(struct platform_device *pdev)
>       if (!hcp)
>               return -ENOMEM;
>  
> +     hcp->id = hdmi_last_id;
>       hcp->hcd = *hcd;
>       mutex_init(&hcp->current_stream_lock);
>  
> @@ -795,6 +826,7 @@ static int hdmi_codec_probe(struct platform_device *pdev)
>       }
>  
>       dev_set_drvdata(dev, hcp);
> +     hdmi_last_id++;
>       return 0;
>  }
>  
> -- 
> 1.9.1
> 
> 

Reply via email to