MLK-17620-1: hdp: register generic hdmi codec driver
authorShengjiu Wang <shengjiu.wang@nxp.com>
Mon, 26 Feb 2018 07:12:32 +0000 (15:12 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:55:28 +0000 (14:55 -0500)
Register generic hdmi codec driver, and move audio related
code to an independent file.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Sandor Yu <sandor.yu@nxp.com>
drivers/gpu/drm/imx/hdp/Makefile
drivers/gpu/drm/imx/hdp/imx-hdp-audio.c [new file with mode: 0644]
drivers/gpu/drm/imx/hdp/imx-hdp.c
drivers/gpu/drm/imx/hdp/imx-hdp.h

index 20bdab8..d289e04 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_IMX_HDP) += imx-hdp.o \
                        API_AFE_ss28fdsoi_kiran_hdmitx.o \
                        API_AFE_t28hpc_hdmitx.o \
                        ss28fdsoi_hdmitx_table.o \
-                       API_AFE_mcu1_dp.o
+                       API_AFE_mcu1_dp.o \
+                       imx-hdp-audio.o
 
 obj-$(CONFIG_IMX_HDP_CEC) += imx-cec.o \
diff --git a/drivers/gpu/drm/imx/hdp/imx-hdp-audio.c b/drivers/gpu/drm/imx/hdp/imx-hdp-audio.c
new file mode 100644 (file)
index 0000000..afc5c6b
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/component.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/irq.h>
+#include <linux/of_device.h>
+#include <sound/hdmi-codec.h>
+
+#include "imx-hdp.h"
+#include "imx-hdmi.h"
+#include "imx-dp.h"
+#include "../imx-drm.h"
+
+static u32 TMDS_rate_table[7] = {
+25200, 27000, 54000, 74250, 148500, 297000, 594000,
+};
+
+static u32 N_table_32k[8] = {
+/*25200, 27000, 54000, 74250, 148500, 297000, 594000,*/
+4096, 4096, 4096, 4096, 4096, 3072, 3072, 4096,
+};
+
+static u32 N_table_44k[8] = {
+6272, 6272, 6272, 6272, 6272, 4704, 9408, 6272,
+};
+
+static u32 N_table_48k[8] = {
+6144, 6144, 6144, 6144, 6144, 5120, 6144, 6144,
+};
+
+static int select_N_index(int vmode_index)
+{
+
+       int i = 0, j = 0;
+
+       for (i = 0; i < VIC_MODE_COUNT; i++) {
+               if (vic_table[i][23] == vmode_index)
+                       break;
+       }
+
+       if (i == VIC_MODE_COUNT) {
+               DRM_ERROR("vmode is wrong!\n");
+               j = 7;
+               return j;
+       }
+
+       for (j = 0; j < 7; j++) {
+               if (vic_table[i][13] == TMDS_rate_table[j])
+                       break;
+       }
+
+       return j;
+}
+
+static u32 imx_hdp_audio(struct imx_hdp *hdmi, AUDIO_TYPE type, u32 sample_rate, u32 channels, u32 width)
+{
+       AUDIO_FREQ  freq;
+       AUDIO_WIDTH bits;
+       int ncts_n;
+       state_struct *state = &hdmi->state;
+       int idx_n = select_N_index(hdmi->vic);
+
+       switch (sample_rate) {
+       case 32000:
+               freq = AUDIO_FREQ_32;
+               ncts_n = N_table_32k[idx_n];
+               break;
+       case 44100:
+               freq = AUDIO_FREQ_44_1;
+               ncts_n = N_table_44k[idx_n];
+               break;
+       case 48000:
+               freq = AUDIO_FREQ_48;
+               ncts_n = N_table_48k[idx_n];
+               break;
+       case 88200:
+               freq = AUDIO_FREQ_88_2;
+               ncts_n = N_table_44k[idx_n] * 2;
+               break;
+       case 96000:
+               freq = AUDIO_FREQ_96;
+               ncts_n = N_table_48k[idx_n] * 2;
+               break;
+       case 176400:
+               freq = AUDIO_FREQ_176_4;
+               ncts_n = N_table_44k[idx_n] * 4;
+               break;
+       case 192000:
+               freq = AUDIO_FREQ_192;
+               ncts_n = N_table_48k[idx_n] * 4;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (width) {
+       case 16:
+               bits = AUDIO_WIDTH_16;
+               break;
+       case 24:
+               bits = AUDIO_WIDTH_24;
+               break;
+       case 32:
+               bits = AUDIO_WIDTH_32;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+
+       CDN_API_AudioOff_blocking(state, type);
+       CDN_API_AudioAutoConfig_blocking(state,
+                               type,
+                               channels,
+                               freq,
+                               0,
+                               bits,
+                               hdmi->audio_type,
+                               ncts_n,
+                               AUDIO_MUTE_MODE_UNMUTE);
+       return 0;
+}
+
+/*
+ * HDMI audio codec callbacks
+ */
+static int imx_hdp_audio_hw_params(struct device *dev, void *data,
+                                   struct hdmi_codec_daifmt *daifmt,
+                                   struct hdmi_codec_params *params)
+{
+       struct imx_hdp *hdmi = dev_get_drvdata(dev);
+       unsigned int chan = params->cea.channels;
+
+       dev_dbg(hdmi->dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
+               params->sample_rate, params->sample_width, chan);
+
+       if (!hdmi->bridge.encoder)
+               return -ENODEV;
+
+       if (daifmt->fmt == HDMI_I2S)
+               imx_hdp_audio(hdmi,
+                               AUDIO_TYPE_I2S,
+                               params->sample_rate,
+                               chan,
+                               params->sample_width);
+       else if (daifmt->fmt == HDMI_SPDIF)
+               imx_hdp_audio(hdmi,
+                               AUDIO_TYPE_SPIDIF_EXTERNAL,
+                               params->sample_rate,
+                               chan,
+                               params->sample_width);
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static void imx_hdp_audio_shutdown(struct device *dev, void *data)
+{
+}
+
+static int imx_hdp_audio_get_eld(struct device *dev, void *data, uint8_t *buf, size_t len)
+{
+       struct imx_hdp *hdmi = dev_get_drvdata(dev);
+
+       memcpy(buf, hdmi->connector.eld, min(sizeof(hdmi->connector.eld), len));
+
+       return 0;
+}
+
+static const struct hdmi_codec_ops imx_hdp_audio_codec_ops = {
+       .hw_params = imx_hdp_audio_hw_params,
+       .audio_shutdown = imx_hdp_audio_shutdown,
+       .get_eld = imx_hdp_audio_get_eld,
+};
+
+void imx_hdp_register_audio_driver(struct device *dev)
+{
+       struct hdmi_codec_pdata codec_data = {
+               .ops = &imx_hdp_audio_codec_ops,
+               .max_i2s_channels = 8,
+               .i2s = 1,
+       };
+       struct platform_device *pdev;
+
+       pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
+                                            PLATFORM_DEVID_NONE, &codec_data,
+                                            sizeof(codec_data));
+       if (IS_ERR(pdev))
+               return;
+
+       DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME);
+}
+
+
index 7a33901..d40eae9 100644 (file)
@@ -26,7 +26,6 @@
 #include "imx-dp.h"
 #include "../imx-drm.h"
 
-struct imx_hdp *g_hdp;
 struct drm_display_mode *g_mode;
 
 static const struct drm_display_mode edid_cea_modes[] = {
@@ -64,116 +63,6 @@ static inline struct imx_hdp *enc_to_imx_hdp(struct drm_encoder *e)
        return container_of(e, struct imx_hdp, encoder);
 }
 
-static u32 TMDS_rate_table[7] = {
-25200, 27000, 54000, 74250, 148500, 297000, 594000,
-};
-
-static u32 N_table_32k[8] = {
-/*25200, 27000, 54000, 74250, 148500, 297000, 594000,*/
-4096, 4096, 4096, 4096, 4096, 3072, 3072, 4096,
-};
-
-static u32 N_table_44k[8] = {
-6272, 6272, 6272, 6272, 6272, 4704, 9408, 6272,
-};
-
-static u32 N_table_48k[8] = {
-6144, 6144, 6144, 6144, 6144, 5120, 6144, 6144,
-};
-
-static int select_N_index(int vmode_index)
-{
-
-       int i = 0, j = 0;
-
-       for (i = 0; i < VIC_MODE_COUNT; i++) {
-               if (vic_table[i][23] == vmode_index)
-                       break;
-       }
-
-       if (i == VIC_MODE_COUNT) {
-               DRM_ERROR("vmode is wrong!\n");
-               j = 7;
-               return j;
-       }
-
-       for (j = 0; j < 7; j++) {
-               if (vic_table[i][13] == TMDS_rate_table[j])
-                       break;
-       }
-
-       return j;
-}
-
-u32 imx_hdp_audio(AUDIO_TYPE type, u32 sample_rate, u32 channels, u32 width)
-{
-       AUDIO_FREQ  freq;
-       AUDIO_WIDTH bits;
-       int ncts_n;
-       state_struct *state = &g_hdp->state;
-       int idx_n = select_N_index(g_hdp->vic);
-
-       switch (sample_rate) {
-       case 32000:
-               freq = AUDIO_FREQ_32;
-               ncts_n = N_table_32k[idx_n];
-               break;
-       case 44100:
-               freq = AUDIO_FREQ_44_1;
-               ncts_n = N_table_44k[idx_n];
-               break;
-       case 48000:
-               freq = AUDIO_FREQ_48;
-               ncts_n = N_table_48k[idx_n];
-               break;
-       case 88200:
-               freq = AUDIO_FREQ_88_2;
-               ncts_n = N_table_44k[idx_n] * 2;
-               break;
-       case 96000:
-               freq = AUDIO_FREQ_96;
-               ncts_n = N_table_48k[idx_n] * 2;
-               break;
-       case 176400:
-               freq = AUDIO_FREQ_176_4;
-               ncts_n = N_table_44k[idx_n] * 4;
-               break;
-       case 192000:
-               freq = AUDIO_FREQ_192;
-               ncts_n = N_table_48k[idx_n] * 4;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (width) {
-       case 16:
-               bits = AUDIO_WIDTH_16;
-               break;
-       case 24:
-               bits = AUDIO_WIDTH_24;
-               break;
-       case 32:
-               bits = AUDIO_WIDTH_32;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-
-       CDN_API_AudioOff_blocking(state, type);
-       CDN_API_AudioAutoConfig_blocking(state,
-                               type,
-                               channels,
-                               freq,
-                               0,
-                               bits,
-                               g_hdp->audio_type,
-                               ncts_n,
-                               AUDIO_MUTE_MODE_UNMUTE);
-       return 0;
-}
-
 static void imx_hdp_state_init(struct imx_hdp *hdp)
 {
        state_struct *state = &hdp->state;
@@ -1044,7 +933,6 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
        bridge = &hdp->bridge;
        connector = &hdp->connector;
 
-       g_hdp = hdp;
        mutex_init(&hdp->mutex);
 
        hdp->irq[HPD_IRQ_IN] = platform_get_irq_byname(pdev, "plug_in");
@@ -1141,6 +1029,7 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
                         DRM_MODE_ENCODER_TMDS, NULL);
 
        /* bridge */
+       bridge->encoder = encoder;
        bridge->driver_private = hdp;
        bridge->funcs = &imx_hdp_bridge_funcs;
        ret = drm_bridge_attach(drm, bridge);
@@ -1203,6 +1092,8 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
                imx_cec_register(&hdp->cec);
 #endif
 
+       imx_hdp_register_audio_driver(dev);
+
        return 0;
 err_irq:
        drm_encoder_cleanup(encoder);
index d2bb902..7b5cfd8 100644 (file)
@@ -225,7 +225,7 @@ struct imx_hdp {
        struct imx_cec_dev cec;
 };
 
-u32 imx_hdp_audio(AUDIO_TYPE type, u32 sample_rate, u32 channels, u32 width);
+void imx_hdp_register_audio_driver(struct device *dev);
 void imx_arc_power_up(state_struct *state);
 void imx_arc_calibrate(state_struct *state);
 void imx_arc_config(state_struct *state);