Merge remote-tracking branch 'sound-asoc/for-next'
[deliverable/linux.git] / sound / soc / codecs / hdmi-codec.c
index f27d115626db7d4cb250c41e788eb5f4b329d91c..b904492d774473a99d5e1aa451f18ff276f83732 100644 (file)
 
 #include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */
 
+struct hdmi_device {
+       struct device *dev;
+       struct list_head list;
+       int cnt;
+};
+#define pos_to_hdmi_device(pos)        container_of((pos), struct hdmi_device, list)
+LIST_HEAD(hdmi_device_list);
+
+#define DAI_NAME_SIZE 16
 struct hdmi_codec_priv {
        struct hdmi_codec_pdata hcd;
        struct snd_soc_dai_driver *daidrv;
@@ -320,7 +329,6 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = {
                         SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
 
 static struct snd_soc_dai_driver hdmi_i2s_dai = {
-       .name = "i2s-hifi",
        .id = DAI_ID_I2S,
        .playback = {
                .stream_name = "Playback",
@@ -334,7 +342,6 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = {
 };
 
 static const struct snd_soc_dai_driver hdmi_spdif_dai = {
-       .name = "spdif-hifi",
        .id = DAI_ID_SPDIF,
        .playback = {
                .stream_name = "Playback",
@@ -346,13 +353,37 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = {
        .ops = &hdmi_dai_ops,
 };
 
+static char hdmi_dai_name[][DAI_NAME_SIZE] = {
+       "hdmi-hifi.0",
+       "hdmi-hifi.1",
+       "hdmi-hifi.2",
+       "hdmi-hifi.3",
+};
+
+static int hdmi_of_xlate_dai_name(struct snd_soc_component *component,
+                                 struct of_phandle_args *args,
+                                 const char **dai_name)
+{
+       int id = args->args[0];
+
+       if (id < ARRAY_SIZE(hdmi_dai_name)) {
+               *dai_name = hdmi_dai_name[id];
+               return 0;
+       }
+
+       return -EAGAIN;
+}
+
 static struct snd_soc_codec_driver hdmi_codec = {
-       .controls = hdmi_controls,
-       .num_controls = ARRAY_SIZE(hdmi_controls),
-       .dapm_widgets = hdmi_widgets,
-       .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
-       .dapm_routes = hdmi_routes,
-       .num_dapm_routes = ARRAY_SIZE(hdmi_routes),
+       .component_driver = {
+               .controls               = hdmi_controls,
+               .num_controls           = ARRAY_SIZE(hdmi_controls),
+               .dapm_widgets           = hdmi_widgets,
+               .num_dapm_widgets       = ARRAY_SIZE(hdmi_widgets),
+               .dapm_routes            = hdmi_routes,
+               .num_dapm_routes        = ARRAY_SIZE(hdmi_routes),
+               .of_xlate_dai_name      = hdmi_of_xlate_dai_name,
+       },
 };
 
 static int hdmi_codec_probe(struct platform_device *pdev)
@@ -360,6 +391,8 @@ static int hdmi_codec_probe(struct platform_device *pdev)
        struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
        struct device *dev = &pdev->dev;
        struct hdmi_codec_priv *hcp;
+       struct hdmi_device *hd;
+       struct list_head *pos;
        int dai_count, i = 0;
        int ret;
 
@@ -381,6 +414,31 @@ static int hdmi_codec_probe(struct platform_device *pdev)
        if (!hcp)
                return -ENOMEM;
 
+       hd = NULL;
+       list_for_each(pos, &hdmi_device_list) {
+               struct hdmi_device *tmp = pos_to_hdmi_device(pos);
+
+               if (tmp->dev == dev->parent) {
+                       hd = tmp;
+                       break;
+               }
+       }
+
+       if (!hd) {
+               hd = devm_kzalloc(dev, sizeof(*hd), GFP_KERNEL);
+               if (!hd)
+                       return -ENOMEM;
+
+               hd->dev = dev->parent;
+
+               list_add_tail(&hd->list, &hdmi_device_list);
+       }
+
+       if (hd->cnt >= ARRAY_SIZE(hdmi_dai_name)) {
+               dev_err(dev, "too many hdmi codec are deteced\n");
+               return -EINVAL;
+       }
+
        hcp->hcd = *hcd;
        mutex_init(&hcp->current_stream_lock);
 
@@ -393,11 +451,14 @@ static int hdmi_codec_probe(struct platform_device *pdev)
                hcp->daidrv[i] = hdmi_i2s_dai;
                hcp->daidrv[i].playback.channels_max =
                        hcd->max_i2s_channels;
+               hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++];
                i++;
        }
 
-       if (hcd->spdif)
+       if (hcd->spdif) {
                hcp->daidrv[i] = hdmi_spdif_dai;
+               hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++];
+       }
 
        ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv,
                                     dai_count);
This page took 0.027184 seconds and 5 git commands to generate.