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. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAl3nqUkTHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zob7fEAC58H3yuqwztw2lmf3rZNPqDh3imClQ XCq8bMNDun09rus1H5qz3+GEj1ADhwKdNGI+It8GTEOSruCewAv5OClk04Ios/7p p0cyN+glbn0QEoK+pxCq1HxYk4H4QVjUg37X8n/zHag6d2Th8A6lR6mAzV/Uq/I4 D31/3sX83+YxhdIu+XN/69yLkqIiWlSU8CT17gXvSO9wZGu23rgzngWy4TbrNRUw C/SHa2Eb/f11xssepXazCRvfz5s++cdfgG5EWg5Ux2v/2zpuP5yDZiWYMa0aM1lY qhuGFEdea51KMMU6JRA0zckuYj4y0nhElgHqzNhUeeKQokDnvNB9NxsSXUKJgtB9 QiFIJCvLYE4WCiPqjjaNel/kZQ4NJw8PppqnQYnGsYW8jXP7GT1B9h+KBMFDPT6F nG6+eYgBCpL81A70q38zn/NV1IP48n6KVrsFI6g+5qi+iJsQVXbhGFWHLAkJVzJB rSYKpU8CfyR0zXQKVJa5ikqfpC9W4FoUtpTh3KTOFcO7f54RGms2O/l2DU/F1Iu3 Qz5EyXYBk8MmDlN/zjTeEiorQXLQMzBSDaJPJ0jqcpFehVkHceWNpCvsIXAX9RCR W6zGTNOmWVwZSv5cRWv9XWIP2LQczSsjw4HJqQyBaCIrGnwVDxX7IImCvqkQSyTp sCOIBX0tnIvRWw== =3LYB -----END PGP SIGNATURE----- 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: Dave 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
This commit is contained in:
Коммит
b7fa0cde29
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче