Commit b7fa0cde authored by Dave Airlie's avatar Dave Airlie

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

drm/tegra: Fixes for v5.5-rc1

This is a set of small fixes, mostly for regressions introduced with the
DMA API and DisplayPort support in the main pull request for v5.5-rc1.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Thierry Reding <thierry.reding@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191204124316.3534855-1-thierry.reding@gmail.com
parents 4673402e d66dfcf8
......@@ -837,16 +837,15 @@ static int tegra_cursor_atomic_check(struct drm_plane *plane,
static void tegra_cursor_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct tegra_bo *bo = tegra_fb_get_plane(plane->state->fb, 0);
struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
struct drm_plane_state *state = plane->state;
u32 value = CURSOR_CLIP_DISPLAY;
/* rien ne va plus */
if (!plane->state->crtc || !plane->state->fb)
return;
switch (state->crtc_w) {
switch (plane->state->crtc_w) {
case 32:
value |= CURSOR_SIZE_32x32;
break;
......@@ -864,16 +863,16 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
break;
default:
WARN(1, "cursor size %ux%u not supported\n", state->crtc_w,
state->crtc_h);
WARN(1, "cursor size %ux%u not supported\n",
plane->state->crtc_w, plane->state->crtc_h);
return;
}
value |= (bo->iova >> 10) & 0x3fffff;
value |= (state->iova[0] >> 10) & 0x3fffff;
tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
value = (bo->iova >> 32) & 0x3;
value = (state->iova[0] >> 32) & 0x3;
tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
#endif
......@@ -892,7 +891,8 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
/* position the cursor */
value = (state->crtc_y & 0x3fff) << 16 | (state->crtc_x & 0x3fff);
value = (plane->state->crtc_y & 0x3fff) << 16 |
(plane->state->crtc_x & 0x3fff);
tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
}
......@@ -2017,7 +2017,7 @@ static int tegra_dc_init(struct host1x_client *client)
dev_warn(dc->dev, "failed to allocate syncpoint\n");
err = host1x_client_iommu_attach(client);
if (err < 0) {
if (err < 0 && err != -ENODEV) {
dev_err(client->dev, "failed to attach to domain: %d\n", err);
return err;
}
......
......@@ -920,10 +920,8 @@ int host1x_client_iommu_attach(struct host1x_client *client)
if (tegra->domain) {
group = iommu_group_get(client->dev);
if (!group) {
dev_err(client->dev, "failed to get IOMMU group\n");
if (!group)
return -ENODEV;
}
if (domain != tegra->domain) {
err = iommu_attach_group(tegra->domain, group);
......@@ -1243,6 +1241,9 @@ static int host1x_drm_remove(struct host1x_device *dev)
drm_atomic_helper_shutdown(drm);
drm_mode_config_cleanup(drm);
if (tegra->hub)
tegra_display_hub_cleanup(tegra->hub);
err = host1x_device_exit(dev);
if (err < 0)
dev_err(&dev->dev, "host1x device cleanup failed: %d\n", err);
......
......@@ -27,6 +27,29 @@ static void tegra_bo_put(struct host1x_bo *bo)
drm_gem_object_put_unlocked(&obj->gem);
}
/* XXX move this into lib/scatterlist.c? */
static int sg_alloc_table_from_sg(struct sg_table *sgt, struct scatterlist *sg,
unsigned int nents, gfp_t gfp_mask)
{
struct scatterlist *dst;
unsigned int i;
int err;
err = sg_alloc_table(sgt, nents, gfp_mask);
if (err < 0)
return err;
dst = sgt->sgl;
for (i = 0; i < nents; i++) {
sg_set_page(dst, sg_page(sg), sg->length, 0);
dst = sg_next(dst);
sg = sg_next(sg);
}
return 0;
}
static struct sg_table *tegra_bo_pin(struct device *dev, struct host1x_bo *bo,
dma_addr_t *phys)
{
......@@ -52,11 +75,31 @@ static struct sg_table *tegra_bo_pin(struct device *dev, struct host1x_bo *bo,
return ERR_PTR(-ENOMEM);
if (obj->pages) {
/*
* If the buffer object was allocated from the explicit IOMMU
* API code paths, construct an SG table from the pages.
*/
err = sg_alloc_table_from_pages(sgt, obj->pages, obj->num_pages,
0, obj->gem.size, GFP_KERNEL);
if (err < 0)
goto free;
} else if (obj->sgt) {
/*
* If the buffer object already has an SG table but no pages
* were allocated for it, it means the buffer was imported and
* the SG table needs to be copied to avoid overwriting any
* other potential users of the original SG table.
*/
err = sg_alloc_table_from_sg(sgt, obj->sgt->sgl, obj->sgt->nents,
GFP_KERNEL);
if (err < 0)
goto free;
} else {
/*
* If the buffer object had no pages allocated and if it was
* not imported, it had to be allocated with the DMA API, so
* the DMA API helper can be used.
*/
err = dma_get_sgtable(dev, sgt, obj->vaddr, obj->iova,
obj->gem.size);
if (err < 0)
......@@ -397,13 +440,6 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
err = tegra_bo_iommu_map(tegra, bo);
if (err < 0)
goto detach;
} else {
if (bo->sgt->nents > 1) {
err = -EINVAL;
goto detach;
}
bo->iova = sg_dma_address(bo->sgt->sgl);
}
bo->gem.import_attach = attach;
......
......@@ -605,11 +605,8 @@ static struct tegra_display_hub_state *
tegra_display_hub_get_state(struct tegra_display_hub *hub,
struct drm_atomic_state *state)
{
struct drm_device *drm = dev_get_drvdata(hub->client.parent);
struct drm_private_state *priv;
WARN_ON(!drm_modeset_is_locked(&drm->mode_config.connection_mutex));
priv = drm_atomic_get_private_obj_state(state, &hub->base);
if (IS_ERR(priv))
return ERR_CAST(priv);
......
......@@ -129,6 +129,17 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state)
goto unpin;
}
/*
* The display controller needs contiguous memory, so
* fail if the buffer is discontiguous and we fail to
* map its SG table to a single contiguous chunk of
* I/O virtual memory.
*/
if (err > 1) {
err = -EINVAL;
goto unpin;
}
state->iova[i] = sg_dma_address(sgt->sgl);
state->sgt[i] = sgt;
} else {
......
......@@ -3912,8 +3912,7 @@ static int tegra_sor_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
static int tegra_sor_suspend(struct device *dev)
static int tegra_sor_runtime_suspend(struct device *dev)
{
struct tegra_sor *sor = dev_get_drvdata(dev);
int err;
......@@ -3935,7 +3934,7 @@ static int tegra_sor_suspend(struct device *dev)
return 0;
}
static int tegra_sor_resume(struct device *dev)
static int tegra_sor_runtime_resume(struct device *dev)
{
struct tegra_sor *sor = dev_get_drvdata(dev);
int err;
......@@ -3967,10 +3966,39 @@ static int tegra_sor_resume(struct device *dev)
return 0;
}
#endif
static int tegra_sor_suspend(struct device *dev)
{
struct tegra_sor *sor = dev_get_drvdata(dev);
int err;
if (sor->hdmi_supply) {
err = regulator_disable(sor->hdmi_supply);
if (err < 0)
return err;
}
return 0;
}
static int tegra_sor_resume(struct device *dev)
{
struct tegra_sor *sor = dev_get_drvdata(dev);
int err;
if (sor->hdmi_supply) {
err = regulator_enable(sor->hdmi_supply);
if (err < 0)
return err;
}
return 0;
}
static const struct dev_pm_ops tegra_sor_pm_ops = {
SET_RUNTIME_PM_OPS(tegra_sor_suspend, tegra_sor_resume, NULL)
SET_RUNTIME_PM_OPS(tegra_sor_runtime_suspend, tegra_sor_runtime_resume,
NULL)
SET_SYSTEM_SLEEP_PM_OPS(tegra_sor_suspend, tegra_sor_resume)
};
struct platform_driver tegra_sor_driver = {
......
......@@ -167,7 +167,7 @@ static int vic_init(struct host1x_client *client)
int err;
err = host1x_client_iommu_attach(client);
if (err < 0) {
if (err < 0 && err != -ENODEV) {
dev_err(vic->dev, "failed to attach to domain: %d\n", err);
return err;
}
......@@ -386,13 +386,14 @@ static const struct vic_config vic_t194_config = {
.supports_sid = true,
};
static const struct of_device_id vic_match[] = {
static const struct of_device_id tegra_vic_of_match[] = {
{ .compatible = "nvidia,tegra124-vic", .data = &vic_t124_config },
{ .compatible = "nvidia,tegra210-vic", .data = &vic_t210_config },
{ .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config },
{ .compatible = "nvidia,tegra194-vic", .data = &vic_t194_config },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_vic_of_match);
static int vic_probe(struct platform_device *pdev)
{
......@@ -516,7 +517,7 @@ static const struct dev_pm_ops vic_pm_ops = {
struct platform_driver tegra_vic_driver = {
.driver = {
.name = "tegra-vic",
.of_match_table = vic_match,
.of_match_table = tegra_vic_of_match,
.pm = &vic_pm_ops
},
.probe = vic_probe,
......
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