Commit 2de0b0a1 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm/tegra/for-4.20-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next

drm/tegra: Changes for v4.20-rc1

This contains initial Tegra194 support as well as a couple of fixes for
DMA/IOMMU integration.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Thierry Reding <thierry.reding@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180927205051.30017-1-thierry.reding@gmail.com
parents db9825c9 5ac93f81
...@@ -1988,6 +1988,28 @@ static int tegra_dc_init(struct host1x_client *client) ...@@ -1988,6 +1988,28 @@ static int tegra_dc_init(struct host1x_client *client)
struct drm_plane *cursor = NULL; struct drm_plane *cursor = NULL;
int err; int err;
/*
* XXX do not register DCs with no window groups because we cannot
* assign a primary plane to them, which in turn will cause KMS to
* crash.
*/
if (dc->soc->wgrps) {
bool has_wgrps = false;
unsigned int i;
for (i = 0; i < dc->soc->num_wgrps; i++) {
const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];
if (wgrp->dc == dc->pipe && wgrp->num_windows > 0) {
has_wgrps = true;
break;
}
}
if (!has_wgrps)
return 0;
}
dc->syncpt = host1x_syncpt_request(client, flags); dc->syncpt = host1x_syncpt_request(client, flags);
if (!dc->syncpt) if (!dc->syncpt)
dev_warn(dc->dev, "failed to allocate syncpoint\n"); dev_warn(dc->dev, "failed to allocate syncpoint\n");
...@@ -2234,8 +2256,59 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = { ...@@ -2234,8 +2256,59 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
.num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps), .num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),
}; };
static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = {
{
.index = 0,
.dc = 0,
.windows = (const unsigned int[]) { 0 },
.num_windows = 1,
}, {
.index = 1,
.dc = 1,
.windows = (const unsigned int[]) { 1 },
.num_windows = 1,
}, {
.index = 2,
.dc = 1,
.windows = (const unsigned int[]) { 2 },
.num_windows = 1,
}, {
.index = 3,
.dc = 2,
.windows = (const unsigned int[]) { 3 },
.num_windows = 1,
}, {
.index = 4,
.dc = 2,
.windows = (const unsigned int[]) { 4 },
.num_windows = 1,
}, {
.index = 5,
.dc = 2,
.windows = (const unsigned int[]) { 5 },
.num_windows = 1,
},
};
static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
.supports_background_color = true,
.supports_interlacing = true,
.supports_cursor = true,
.supports_block_linear = true,
.has_legacy_blending = false,
.pitch_align = 64,
.has_powergate = false,
.coupled_pm = false,
.has_nvdisplay = true,
.wgrps = tegra194_dc_wgrps,
.num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps),
};
static const struct of_device_id tegra_dc_of_match[] = { static const struct of_device_id tegra_dc_of_match[] = {
{ {
.compatible = "nvidia,tegra194-dc",
.data = &tegra194_dc_soc_info,
}, {
.compatible = "nvidia,tegra186-dc", .compatible = "nvidia,tegra186-dc",
.data = &tegra186_dc_soc_info, .data = &tegra186_dc_soc_info,
}, { }, {
......
...@@ -300,7 +300,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); ...@@ -300,7 +300,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define SOR1_TIMING_CYA (1 << 27) #define SOR1_TIMING_CYA (1 << 27)
#define CURSOR_ENABLE (1 << 16) #define CURSOR_ENABLE (1 << 16)
#define SOR_ENABLE(x) (1 << (25 + (x))) #define SOR_ENABLE(x) (1 << (25 + (((x) > 1) ? ((x) + 1) : (x))))
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) #define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
......
...@@ -521,7 +521,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev) ...@@ -521,7 +521,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
* is no possibility to perform the I2C mode configuration in the * is no possibility to perform the I2C mode configuration in the
* HDMI path. * HDMI path.
*/ */
err = tegra_dpaux_pad_config(dpaux, DPAUX_HYBRID_PADCTL_MODE_I2C); err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
if (err < 0) if (err < 0)
return err; return err;
...@@ -639,6 +639,7 @@ static const struct dev_pm_ops tegra_dpaux_pm_ops = { ...@@ -639,6 +639,7 @@ static const struct dev_pm_ops tegra_dpaux_pm_ops = {
}; };
static const struct of_device_id tegra_dpaux_of_match[] = { static const struct of_device_id tegra_dpaux_of_match[] = {
{ .compatible = "nvidia,tegra194-dpaux", },
{ .compatible = "nvidia,tegra186-dpaux", }, { .compatible = "nvidia,tegra186-dpaux", },
{ .compatible = "nvidia,tegra210-dpaux", }, { .compatible = "nvidia,tegra210-dpaux", },
{ .compatible = "nvidia,tegra124-dpaux", }, { .compatible = "nvidia,tegra124-dpaux", },
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
#include <drm/drm_atomic.h> #include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
#include <asm/dma-iommu.h>
#endif
#include "drm.h" #include "drm.h"
#include "gem.h" #include "gem.h"
...@@ -1068,6 +1072,14 @@ struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client, ...@@ -1068,6 +1072,14 @@ struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client,
} }
if (!shared || (shared && (group != tegra->group))) { if (!shared || (shared && (group != tegra->group))) {
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
if (client->dev->archdata.mapping) {
struct dma_iommu_mapping *mapping =
to_dma_iommu_mapping(client->dev);
arm_iommu_detach_device(client->dev);
arm_iommu_release_mapping(mapping);
}
#endif
err = iommu_attach_group(tegra->domain, group); err = iommu_attach_group(tegra->domain, group);
if (err < 0) { if (err < 0) {
iommu_group_put(group); iommu_group_put(group);
...@@ -1216,31 +1228,15 @@ static int host1x_drm_remove(struct host1x_device *dev) ...@@ -1216,31 +1228,15 @@ static int host1x_drm_remove(struct host1x_device *dev)
static int host1x_drm_suspend(struct device *dev) static int host1x_drm_suspend(struct device *dev)
{ {
struct drm_device *drm = dev_get_drvdata(dev); struct drm_device *drm = dev_get_drvdata(dev);
struct tegra_drm *tegra = drm->dev_private;
drm_kms_helper_poll_disable(drm);
tegra_drm_fb_suspend(drm);
tegra->state = drm_atomic_helper_suspend(drm); return drm_mode_config_helper_suspend(drm);
if (IS_ERR(tegra->state)) {
tegra_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm);
return PTR_ERR(tegra->state);
}
return 0;
} }
static int host1x_drm_resume(struct device *dev) static int host1x_drm_resume(struct device *dev)
{ {
struct drm_device *drm = dev_get_drvdata(dev); struct drm_device *drm = dev_get_drvdata(dev);
struct tegra_drm *tegra = drm->dev_private;
drm_atomic_helper_resume(drm, tegra->state);
tegra_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm);
return 0; return drm_mode_config_helper_resume(drm);
} }
#endif #endif
...@@ -1275,6 +1271,9 @@ static const struct of_device_id host1x_drm_subdevs[] = { ...@@ -1275,6 +1271,9 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra186-sor", }, { .compatible = "nvidia,tegra186-sor", },
{ .compatible = "nvidia,tegra186-sor1", }, { .compatible = "nvidia,tegra186-sor1", },
{ .compatible = "nvidia,tegra186-vic", }, { .compatible = "nvidia,tegra186-vic", },
{ .compatible = "nvidia,tegra194-display", },
{ .compatible = "nvidia,tegra194-dc", },
{ .compatible = "nvidia,tegra194-sor", },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -60,8 +60,6 @@ struct tegra_drm { ...@@ -60,8 +60,6 @@ struct tegra_drm {
unsigned int pitch_align; unsigned int pitch_align;
struct tegra_display_hub *hub; struct tegra_display_hub *hub;
struct drm_atomic_state *state;
}; };
struct tegra_drm_client; struct tegra_drm_client;
...@@ -186,8 +184,6 @@ int tegra_drm_fb_prepare(struct drm_device *drm); ...@@ -186,8 +184,6 @@ int tegra_drm_fb_prepare(struct drm_device *drm);
void tegra_drm_fb_free(struct drm_device *drm); void tegra_drm_fb_free(struct drm_device *drm);
int tegra_drm_fb_init(struct drm_device *drm); int tegra_drm_fb_init(struct drm_device *drm);
void tegra_drm_fb_exit(struct drm_device *drm); void tegra_drm_fb_exit(struct drm_device *drm);
void tegra_drm_fb_suspend(struct drm_device *drm);
void tegra_drm_fb_resume(struct drm_device *drm);
extern struct platform_driver tegra_display_hub_driver; extern struct platform_driver tegra_display_hub_driver;
extern struct platform_driver tegra_dc_driver; extern struct platform_driver tegra_dc_driver;
......
...@@ -356,7 +356,7 @@ static void tegra_fbdev_exit(struct tegra_fbdev *fbdev) ...@@ -356,7 +356,7 @@ static void tegra_fbdev_exit(struct tegra_fbdev *fbdev)
/* Undo the special mapping we made in fbdev probe. */ /* Undo the special mapping we made in fbdev probe. */
if (bo && bo->pages) { if (bo && bo->pages) {
vunmap(bo->vaddr); vunmap(bo->vaddr);
bo->vaddr = 0; bo->vaddr = NULL;
} }
drm_framebuffer_remove(fbdev->fb); drm_framebuffer_remove(fbdev->fb);
...@@ -412,25 +412,3 @@ void tegra_drm_fb_exit(struct drm_device *drm) ...@@ -412,25 +412,3 @@ void tegra_drm_fb_exit(struct drm_device *drm)
tegra_fbdev_exit(tegra->fbdev); tegra_fbdev_exit(tegra->fbdev);
#endif #endif
} }
void tegra_drm_fb_suspend(struct drm_device *drm)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
console_lock();
drm_fb_helper_set_suspend(&tegra->fbdev->base, 1);
console_unlock();
#endif
}
void tegra_drm_fb_resume(struct drm_device *drm)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
console_lock();
drm_fb_helper_set_suspend(&tegra->fbdev->base, 0);
console_unlock();
#endif
}
...@@ -758,10 +758,12 @@ static int tegra_display_hub_probe(struct platform_device *pdev) ...@@ -758,10 +758,12 @@ static int tegra_display_hub_probe(struct platform_device *pdev)
return err; return err;
} }
hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc"); if (hub->soc->supports_dsc) {
if (IS_ERR(hub->clk_dsc)) { hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
err = PTR_ERR(hub->clk_dsc); if (IS_ERR(hub->clk_dsc)) {
return err; err = PTR_ERR(hub->clk_dsc);
return err;
}
} }
hub->clk_hub = devm_clk_get(&pdev->dev, "hub"); hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
...@@ -890,10 +892,19 @@ static const struct dev_pm_ops tegra_display_hub_pm_ops = { ...@@ -890,10 +892,19 @@ static const struct dev_pm_ops tegra_display_hub_pm_ops = {
static const struct tegra_display_hub_soc tegra186_display_hub = { static const struct tegra_display_hub_soc tegra186_display_hub = {
.num_wgrps = 6, .num_wgrps = 6,
.supports_dsc = true,
};
static const struct tegra_display_hub_soc tegra194_display_hub = {
.num_wgrps = 6,
.supports_dsc = false,
}; };
static const struct of_device_id tegra_display_hub_of_match[] = { static const struct of_device_id tegra_display_hub_of_match[] = {
{ {
.compatible = "nvidia,tegra194-display",
.data = &tegra194_display_hub
}, {
.compatible = "nvidia,tegra186-display", .compatible = "nvidia,tegra186-display",
.data = &tegra186_display_hub .data = &tegra186_display_hub
}, { }, {
......
...@@ -38,6 +38,7 @@ to_tegra_shared_plane(struct drm_plane *plane) ...@@ -38,6 +38,7 @@ to_tegra_shared_plane(struct drm_plane *plane)
struct tegra_display_hub_soc { struct tegra_display_hub_soc {
unsigned int num_wgrps; unsigned int num_wgrps;
bool supports_dsc;
}; };
struct tegra_display_hub { struct tegra_display_hub {
......
...@@ -282,6 +282,85 @@ static const struct tegra_sor_hdmi_settings tegra186_sor_hdmi_defaults[] = { ...@@ -282,6 +282,85 @@ static const struct tegra_sor_hdmi_settings tegra186_sor_hdmi_defaults[] = {
} }
}; };
static const struct tegra_sor_hdmi_settings tegra194_sor_hdmi_defaults[] = {
{
.frequency = 54000000,
.vcocap = 0,
.filter = 5,
.ichpmp = 5,
.loadadj = 3,
.tmds_termadj = 0xf,
.tx_pu_value = 0,
.bg_temp_coef = 3,
.bg_vref_level = 8,
.avdd10_level = 4,
.avdd14_level = 4,
.sparepll = 0x54,
.drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
.preemphasis = { 0x00, 0x00, 0x00, 0x00 },
}, {
.frequency = 75000000,
.vcocap = 1,
.filter = 5,
.ichpmp = 5,
.loadadj = 3,
.tmds_termadj = 0xf,
.tx_pu_value = 0,
.bg_temp_coef = 3,
.bg_vref_level = 8,
.avdd10_level = 4,
.avdd14_level = 4,
.sparepll = 0x44,
.drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
.preemphasis = { 0x00, 0x00, 0x00, 0x00 },
}, {
.frequency = 150000000,
.vcocap = 3,
.filter = 5,
.ichpmp = 5,
.loadadj = 3,
.tmds_termadj = 15,
.tx_pu_value = 0x66 /* 0 */,
.bg_temp_coef = 3,
.bg_vref_level = 8,
.avdd10_level = 4,
.avdd14_level = 4,
.sparepll = 0x00, /* 0x34 */
.drive_current = { 0x3a, 0x3a, 0x3a, 0x37 },
.preemphasis = { 0x00, 0x00, 0x00, 0x00 },
}, {
.frequency = 300000000,
.vcocap = 3,
.filter = 5,
.ichpmp = 5,
.loadadj = 3,
.tmds_termadj = 15,
.tx_pu_value = 64,
.bg_temp_coef = 3,
.bg_vref_level = 8,
.avdd10_level = 4,
.avdd14_level = 4,
.sparepll = 0x34,
.drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
.preemphasis = { 0x00, 0x00, 0x00, 0x00 },
}, {
.frequency = 600000000,
.vcocap = 3,
.filter = 5,
.ichpmp = 5,
.loadadj = 3,
.tmds_termadj = 12,
.tx_pu_value = 96,
.bg_temp_coef = 3,
.bg_vref_level = 8,
.avdd10_level = 4,
.avdd14_level = 4,
.sparepll = 0x34,
.drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
.preemphasis = { 0x00, 0x00, 0x00, 0x00 },
}
};
struct tegra_sor_regs { struct tegra_sor_regs {
unsigned int head_state0; unsigned int head_state0;
unsigned int head_state1; unsigned int head_state1;
...@@ -2894,7 +2973,38 @@ static const struct tegra_sor_soc tegra186_sor1 = { ...@@ -2894,7 +2973,38 @@ static const struct tegra_sor_soc tegra186_sor1 = {
.xbar_cfg = tegra124_sor_xbar_cfg, .xbar_cfg = tegra124_sor_xbar_cfg,
}; };
static const struct tegra_sor_regs tegra194_sor_regs = {
.head_state0 = 0x151,
.head_state1 = 0x155,
.head_state2 = 0x159,
.head_state3 = 0x15d,
.head_state4 = 0x161,
.head_state5 = 0x165,
.pll0 = 0x169,
.pll1 = 0x16a,
.pll2 = 0x16b,
.pll3 = 0x16c,
.dp_padctl0 = 0x16e,
.dp_padctl2 = 0x16f,
};
static const struct tegra_sor_soc tegra194_sor = {
.supports_edp = true,
.supports_lvds = false,
.supports_hdmi = true,
.supports_dp = true,
.regs = &tegra194_sor_regs,
.has_nvdisplay = true,
.num_settings = ARRAY_SIZE(tegra194_sor_hdmi_defaults),
.settings = tegra194_sor_hdmi_defaults,
.xbar_cfg = tegra210_sor_xbar_cfg,
};
static const struct of_device_id tegra_sor_of_match[] = { static const struct of_device_id tegra_sor_of_match[] = {
{ .compatible = "nvidia,tegra194-sor", .data = &tegra194_sor },
{ .compatible = "nvidia,tegra186-sor1", .data = &tegra186_sor1 }, { .compatible = "nvidia,tegra186-sor1", .data = &tegra186_sor1 },
{ .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor }, { .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor },
{ .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 }, { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 },
......
...@@ -331,7 +331,7 @@ static const struct dev_pm_ops host1x_device_pm_ops = { ...@@ -331,7 +331,7 @@ static const struct dev_pm_ops host1x_device_pm_ops = {
struct bus_type host1x_bus_type = { struct bus_type host1x_bus_type = {
.name = "host1x", .name = "host1x",
.match = host1x_device_match, .match = host1x_device_match,
.dma_configure = host1x_dma_configure, .dma_configure = host1x_dma_configure,
.pm = &host1x_device_pm_ops, .pm = &host1x_device_pm_ops,
}; };
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
#include <trace/events/host1x.h> #include <trace/events/host1x.h>
#undef CREATE_TRACE_POINTS #undef CREATE_TRACE_POINTS
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
#include <asm/dma-iommu.h>
#endif
#include "bus.h" #include "bus.h"
#include "channel.h" #include "channel.h"
#include "debug.h" #include "debug.h"
...@@ -217,7 +221,14 @@ static int host1x_probe(struct platform_device *pdev) ...@@ -217,7 +221,14 @@ static int host1x_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get reset: %d\n", err); dev_err(&pdev->dev, "failed to get reset: %d\n", err);
return err; return err;
} }
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
if (host->dev->archdata.mapping) {
struct dma_iommu_mapping *mapping =
to_dma_iommu_mapping(host->dev);
arm_iommu_detach_device(host->dev);
arm_iommu_release_mapping(mapping);
}
#endif
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
goto skip_iommu; goto skip_iommu;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment