summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/tegra/sor.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2019-02-11 06:32:38 +0300
committerDave Airlie <airlied@redhat.com>2019-02-11 06:32:49 +0300
commit38f070eb125a9253ec1acd641e7159555f57132a (patch)
treea5e146cc0f8dbf5486ef8ae14a77e50164ee1ac0 /drivers/gpu/drm/tegra/sor.c
parent0ad7fb7c7b973ca4cea341282a60d056393d8034 (diff)
parent79930bafe2802c3a67a70ad4904032d9154bf3fa (diff)
downloadlinux-38f070eb125a9253ec1acd641e7159555f57132a.tar.xz
Merge tag 'drm/tegra/for-5.1-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v5.1-rc1 This set of changes starts of with some refactoring of the CEC support to make it reusable on Tegra210 and later. Following are a couple of fixes for HDMI audio support (via HDA). The bulk here is a set of preparatory patches working towards enabling Tegra186 support for host1x and VIC. Additional patches will be needed to fully enable this, but they're not quite ready yet. To round things off, this also adds support for configuring the SOR crossbar using device tree, and fixes a couple of job-related issues in the host1x code. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thierry Reding <thierry.reding@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190208144721.25830-1-thierry.reding@gmail.com
Diffstat (limited to 'drivers/gpu/drm/tegra/sor.c')
-rw-r--r--drivers/gpu/drm/tegra/sor.c64
1 files changed, 27 insertions, 37 deletions
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 44feac2a0359..40057106f5f3 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -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 {