]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/msm/hdmi/hdmi.c
drm: msm: Add ASoC generic hdmi audio codec support.
[karo-tx-linux.git] / drivers / gpu / drm / msm / hdmi / hdmi.c
index ab46e6a743e0145b330c0a041cc4ef843e21d032..be522ac6cc81167f24a2f42966d3f69f4d97b0b5 100644 (file)
@@ -17,8 +17,9 @@
  */
 
 #include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+
 #include <sound/hdmi-codec.h>
-#include <sound/msm_hdmi_audio.h>
 #include "hdmi.h"
 
 void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
@@ -417,7 +418,114 @@ static int get_gpio(struct device *dev, struct device_node *of_node, const char
 }
 #endif
 
-static void msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev);
+/*
+ * HDMI audio codec callbacks
+ */
+static int msm_hdmi_audio_hw_params(struct device *dev,
+                                   struct hdmi_codec_daifmt *daifmt,
+                                   struct hdmi_codec_params *params)
+{
+       struct hdmi *hdmi = dev_get_drvdata(dev);
+       unsigned int chan;
+       unsigned int channel_allocation = 0;
+       unsigned int rate;
+       unsigned int level_shift  = 0; /* 0dB */
+       bool down_mix = false;
+
+       dev_dbg(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate,
+                params->sample_width, params->cea.channels);
+
+       switch (params->cea.channels) {
+       case 2:
+               /* FR and FL speakers */
+               channel_allocation  = 0;
+               chan = MSM_HDMI_AUDIO_CHANNEL_2;
+               break;
+       case 4:
+               /* FC, LFE, FR and FL speakers */
+               channel_allocation  = 0x3;
+               chan = MSM_HDMI_AUDIO_CHANNEL_4;
+               break;
+       case 6:
+               /* RR, RL, FC, LFE, FR and FL speakers */
+               channel_allocation  = 0x0B;
+               chan = MSM_HDMI_AUDIO_CHANNEL_6;
+               break;
+       case 8:
+               /* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */
+               channel_allocation  = 0x1F;
+               chan = MSM_HDMI_AUDIO_CHANNEL_8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (params->sample_rate) {
+       case 32000:
+               rate = HDMI_SAMPLE_RATE_32KHZ;
+               break;
+       case 44100:
+               rate = HDMI_SAMPLE_RATE_44_1KHZ;
+               break;
+       case 48000:
+               rate = HDMI_SAMPLE_RATE_48KHZ;
+               break;
+       case 88200:
+               rate = HDMI_SAMPLE_RATE_88_2KHZ;
+               break;
+       case 96000:
+               rate = HDMI_SAMPLE_RATE_96KHZ;
+               break;
+       case 176400:
+               rate = HDMI_SAMPLE_RATE_176_4KHZ;
+               break;
+       case 192000:
+               rate = HDMI_SAMPLE_RATE_192KHZ;
+               break;
+       default:
+               dev_err(dev, "rate[%d] not supported!\n",
+                       params->sample_rate);
+               return -EINVAL;
+       }
+
+       hdmi_audio_set_sample_rate(hdmi, rate);
+       hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation,
+                             level_shift, down_mix);
+
+       return 0;
+}
+
+static void msm_hdmi_audio_shutdown(struct device *dev)
+{
+       struct hdmi *hdmi = dev_get_drvdata(dev);
+
+       hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0);
+}
+
+static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = {
+       .hw_params = msm_hdmi_audio_hw_params,
+       .audio_shutdown = msm_hdmi_audio_shutdown,
+};
+
+static struct hdmi_codec_pdata codec_data = {
+       .ops = &msm_hdmi_audio_codec_ops,
+       .max_i2s_channels = 8,
+       .i2s = 1,
+};
+
+static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev)
+{
+       hdmi->audio_pdev = platform_device_register_data(dev,
+                                                        HDMI_CODEC_DRV_NAME,
+                                                        PLATFORM_DEVID_AUTO,
+                                                        &codec_data,
+                                                        sizeof(codec_data));
+       if (IS_ERR(hdmi->audio_pdev))
+               return PTR_ERR(hdmi->audio_pdev);
+
+       return 0;
+}
+
 static int hdmi_bind(struct device *dev, struct device *master, void *data)
 {
        struct drm_device *drm = dev_get_drvdata(master);
@@ -427,6 +535,7 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
 #ifdef CONFIG_OF
        struct device_node *of_node = dev->of_node;
        const struct of_device_id *match;
+       int err;
 
        match = of_match_node(dt_match, of_node);
        if (match && match->data) {
@@ -501,7 +610,12 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
        if (IS_ERR(hdmi))
                return PTR_ERR(hdmi);
        priv->hdmi = hdmi;
-       msm_hdmi_register_audio_driver(hdmi, dev);
+
+       err = msm_hdmi_register_audio_driver(hdmi, dev);
+       if (err) {
+               DRM_ERROR("Failed to attach an audio codec %d\n", err);
+               hdmi->audio_pdev = NULL;
+       }
 
        return 0;
 }
@@ -512,9 +626,10 @@ static void hdmi_unbind(struct device *dev, struct device *master,
        struct drm_device *drm = dev_get_drvdata(master);
        struct msm_drm_private *priv = drm->dev_private;
        if (priv->hdmi) {
-               DRM_INFO("%s driver unbound to HDMI\n", HDMI_CODEC_DRV_NAME);
-               platform_device_unregister(priv->hdmi->audio_pdev);
                hdmi_destroy(priv->hdmi);
+               if (priv->hdmi->audio_pdev)
+                       platform_device_unregister(priv->hdmi->audio_pdev);
+
                priv->hdmi = NULL;
        }
 }
@@ -523,124 +638,6 @@ static const struct component_ops hdmi_ops = {
                .bind   = hdmi_bind,
                .unbind = hdmi_unbind,
 };
-/*
- * HDMI audio codec callbacks
- */
-
-static int msm_hdmi_audio_hw_params(struct device *dev,
-                                   struct hdmi_codec_daifmt *daifmt,
-                                   struct hdmi_codec_params *params)
-{
-       struct hdmi *hdmi = dev_get_drvdata(dev);
-       unsigned int chan;// = params->cea.channels;
-       unsigned int channel_allocation = 0;
-       unsigned int rate;//
-       unsigned int level_shift  = 0; /* 0dB */
-       bool down_mix = false;
-       dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
-               params->sample_rate, params->sample_width, chan);
-
-       switch (params->cea.channels) {
-       case 2:
-               channel_allocation  = 0;
-               chan = MSM_HDMI_AUDIO_CHANNEL_2;
-               break;
-       case 4:
-               channel_allocation  = 0;
-               chan = MSM_HDMI_AUDIO_CHANNEL_4;
-               break;
-       case 6:
-               channel_allocation  = 0x0B;
-               chan = MSM_HDMI_AUDIO_CHANNEL_6;
-               break;
-       case 8:
-               channel_allocation  = 0x1F;
-               chan = MSM_HDMI_AUDIO_CHANNEL_8;
-               break;
-       default:
-               //dev_err(hdmi->dev, "channel[%d] not supported!\n", chan);
-               return -EINVAL;
-       }
-
-       switch (params->sample_rate) {
-       case 32000:
-               rate = HDMI_SAMPLE_RATE_32KHZ;
-       case 44100:
-               rate = HDMI_SAMPLE_RATE_48KHZ;
-       case 48000:
-               rate = HDMI_SAMPLE_RATE_48KHZ;
-       case 88200:
-               rate = HDMI_SAMPLE_RATE_88_2KHZ;
-       case 96000:
-               rate = HDMI_SAMPLE_RATE_96KHZ;
-       case 176400:
-               rate = HDMI_SAMPLE_RATE_176_4KHZ;
-       case 192000:
-               rate = HDMI_SAMPLE_RATE_192KHZ;
-               break;
-       default:
-               dev_err(dev, "rate[%d] not supported!\n",
-                       params->sample_rate);
-               return -EINVAL;
-       }
-               rate = HDMI_SAMPLE_RATE_48KHZ;
-               channel_allocation  = 0;
-
-       //FIXME..
-       hdmi_audio_set_sample_rate(hdmi, rate);
-
-       hdmi_audio_info_setup(hdmi, 1, chan,
-                       channel_allocation, level_shift, down_mix);
-
-
-
-       return 0;
-}
-
-static int msm_hdmi_audio_startup(struct device *dev,
-                                 void (*abort_cb)(struct device *dev))
-{
-       struct hdmi *hdmi = dev_get_drvdata(dev);
-
-       dev_dbg(dev, "%s\n", __func__);
-
-       //msm_hdmi_audio_enable(hdmi);
-
-       return 0;
-}
-
-static void msm_hdmi_audio_shutdown(struct device *dev)
-{
-       struct hdmi *hdmi = dev_get_drvdata(dev);
-
-       dev_dbg(dev, "%s\n", __func__);
-
-       hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0);
-}
-
-static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = {
-       .hw_params = msm_hdmi_audio_hw_params,
-       .audio_startup = msm_hdmi_audio_startup,
-       .audio_shutdown = msm_hdmi_audio_shutdown,
-};
-
-static void msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev)
-{
-       struct hdmi_codec_pdata codec_data = {
-               .ops = &msm_hdmi_audio_codec_ops,
-               .max_i2s_channels = 2,
-               .i2s = 1,
-       };
-       //struct platform_device *pdev;
-
-       hdmi->audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
-                                            PLATFORM_DEVID_AUTO, &codec_data,
-                                            sizeof(codec_data));
-       if (IS_ERR(hdmi->audio_pdev))
-               return;
-
-       DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME);
-}
 
 static int hdmi_dev_probe(struct platform_device *pdev)
 {