Merge tag 'drm/tegra/for-5.1-rc1' of git://anongit.freedesktop.org/tegra/linux into...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / tegra / sor.c
index 44feac2a03594445d180e8f2399288cbf9278f06..40057106f5f39e7c6bb29772e7f7c463b6aa34e1 100644 (file)
@@ -19,8 +19,6 @@
 
 #include <soc/tegra/pmc.h>
 
-#include <sound/hda_verbs.h>
-
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_panel.h>
@@ -28,6 +26,7 @@
 
 #include "dc.h"
 #include "drm.h"
+#include "hda.h"
 #include "sor.h"
 #include "trace.h"
 
@@ -411,6 +410,8 @@ struct tegra_sor {
        struct clk *clk_dp;
        struct clk *clk;
 
+       u8 xbar_cfg[5];
+
        struct drm_dp_aux *aux;
 
        struct drm_info_list *debugfs_files;
@@ -429,10 +430,7 @@ struct tegra_sor {
        struct delayed_work scdc;
        bool scdc_enabled;
 
-       struct {
-               unsigned int sample_rate;
-               unsigned int channels;
-       } audio;
+       struct tegra_hda_format format;
 };
 
 struct tegra_sor_state {
@@ -1818,7 +1816,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
 
        /* XXX not in TRM */
        for (value = 0, i = 0; i < 5; i++)
-               value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->soc->xbar_cfg[i]) |
+               value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->xbar_cfg[i]) |
                         SOR_XBAR_CTRL_LINK1_XSEL(i, i);
 
        tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL);
@@ -2186,7 +2184,7 @@ static int tegra_sor_hdmi_enable_audio_infoframe(struct tegra_sor *sor)
                return err;
        }
 
-       frame.channels = sor->audio.channels;
+       frame.channels = sor->format.channels;
 
        err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
        if (err < 0) {
@@ -2215,7 +2213,7 @@ static void tegra_sor_hdmi_audio_enable(struct tegra_sor *sor)
        value |= SOR_AUDIO_CNTRL_SOURCE_SELECT(SOURCE_SELECT_HDA);
 
        /* inject null samples */
-       if (sor->audio.channels != 2)
+       if (sor->format.channels != 2)
                value &= ~SOR_AUDIO_CNTRL_INJECT_NULLSMPL;
        else
                value |= SOR_AUDIO_CNTRL_INJECT_NULLSMPL;
@@ -2246,7 +2244,7 @@ static void tegra_sor_hdmi_audio_enable(struct tegra_sor *sor)
        value = SOR_HDMI_AUDIO_N_RESET | SOR_HDMI_AUDIO_N_LOOKUP;
        tegra_sor_writel(sor, value, SOR_HDMI_AUDIO_N);
 
-       value = (24000 * 4096) / (128 * sor->audio.sample_rate / 1000);
+       value = (24000 * 4096) / (128 * sor->format.sample_rate / 1000);
        tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_0320);
        tegra_sor_writel(sor, 4096, SOR_AUDIO_NVAL_0320);
 
@@ -2259,15 +2257,15 @@ static void tegra_sor_hdmi_audio_enable(struct tegra_sor *sor)
        tegra_sor_writel(sor, 20000, SOR_AUDIO_AVAL_1764);
        tegra_sor_writel(sor, 18816, SOR_AUDIO_NVAL_1764);
 
-       value = (24000 * 6144) / (128 * sor->audio.sample_rate / 1000);
+       value = (24000 * 6144) / (128 * sor->format.sample_rate / 1000);
        tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_0480);
        tegra_sor_writel(sor, 6144, SOR_AUDIO_NVAL_0480);
 
-       value = (24000 * 12288) / (128 * sor->audio.sample_rate / 1000);
+       value = (24000 * 12288) / (128 * sor->format.sample_rate / 1000);
        tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_0960);
        tegra_sor_writel(sor, 12288, SOR_AUDIO_NVAL_0960);
 
-       value = (24000 * 24576) / (128 * sor->audio.sample_rate / 1000);
+       value = (24000 * 24576) / (128 * sor->format.sample_rate / 1000);
        tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_1920);
        tegra_sor_writel(sor, 24576, SOR_AUDIO_NVAL_1920);
 
@@ -2555,7 +2553,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
 
        /* XXX not in TRM */
        for (value = 0, i = 0; i < 5; i++)
-               value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->soc->xbar_cfg[i]) |
+               value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->xbar_cfg[i]) |
                         SOR_XBAR_CTRL_LINK1_XSEL(i, i);
 
        tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL);
@@ -3176,6 +3174,8 @@ MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
 static int tegra_sor_parse_dt(struct tegra_sor *sor)
 {
        struct device_node *np = sor->dev->of_node;
+       u32 xbar_cfg[5];
+       unsigned int i;
        u32 value;
        int err;
 
@@ -3193,25 +3193,18 @@ static int tegra_sor_parse_dt(struct tegra_sor *sor)
                sor->pad = TEGRA_IO_PAD_HDMI_DP0 + sor->index;
        }
 
-       return 0;
-}
-
-static void tegra_hda_parse_format(unsigned int format, unsigned int *rate,
-                                  unsigned int *channels)
-{
-       unsigned int mul, div;
-
-       if (format & AC_FMT_BASE_44K)
-               *rate = 44100;
-       else
-               *rate = 48000;
-
-       mul = (format & AC_FMT_MULT_MASK) >> AC_FMT_MULT_SHIFT;
-       div = (format & AC_FMT_DIV_MASK) >> AC_FMT_DIV_SHIFT;
-
-       *rate = *rate * (mul + 1) / (div + 1);
+       err = of_property_read_u32_array(np, "nvidia,xbar-cfg", xbar_cfg, 5);
+       if (err < 0) {
+               /* fall back to default per-SoC XBAR configuration */
+               for (i = 0; i < 5; i++)
+                       sor->xbar_cfg[i] = sor->soc->xbar_cfg[i];
+       } else {
+               /* copy cells to SOR XBAR configuration */
+               for (i = 0; i < 5; i++)
+                       sor->xbar_cfg[i] = xbar_cfg[i];
+       }
 
-       *channels = (format & AC_FMT_CHAN_MASK) >> AC_FMT_CHAN_SHIFT;
+       return 0;
 }
 
 static irqreturn_t tegra_sor_irq(int irq, void *data)
@@ -3226,14 +3219,11 @@ static irqreturn_t tegra_sor_irq(int irq, void *data)
                value = tegra_sor_readl(sor, SOR_AUDIO_HDA_CODEC_SCRATCH0);
 
                if (value & SOR_AUDIO_HDA_CODEC_SCRATCH0_VALID) {
-                       unsigned int format, sample_rate, channels;
+                       unsigned int format;
 
                        format = value & SOR_AUDIO_HDA_CODEC_SCRATCH0_FMT_MASK;
 
-                       tegra_hda_parse_format(format, &sample_rate, &channels);
-
-                       sor->audio.sample_rate = sample_rate;
-                       sor->audio.channels = channels;
+                       tegra_hda_parse_format(format, &sor->format);
 
                        tegra_sor_hdmi_audio_enable(sor);
                } else {