diff options
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 223 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dpaux.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/fb.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gr2d.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gr3d.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hub.c | 103 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/plane.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 70 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/vic.c | 4 |
13 files changed, 372 insertions, 140 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 134986dc2783..f9120dc24682 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -604,23 +604,25 @@ static const u64 tegra124_modifiers[] = { }; static int tegra_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_atomic_state *state) { - struct tegra_plane_state *plane_state = to_tegra_plane_state(state); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); + struct tegra_plane_state *plane_state = to_tegra_plane_state(new_plane_state); unsigned int supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; - unsigned int rotation = state->rotation; + unsigned int rotation = new_plane_state->rotation; struct tegra_bo_tiling *tiling = &plane_state->tiling; struct tegra_plane *tegra = to_tegra_plane(plane); - struct tegra_dc *dc = to_tegra_dc(state->crtc); + struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc); int err; /* no need for further checks if the plane is being disabled */ - if (!state->crtc) + if (!new_plane_state->crtc) return 0; - err = tegra_plane_format(state->fb->format->format, + err = tegra_plane_format(new_plane_state->fb->format->format, &plane_state->format, &plane_state->swap); if (err < 0) @@ -638,7 +640,7 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, return err; } - err = tegra_fb_get_tiling(state->fb, tiling); + err = tegra_fb_get_tiling(new_plane_state->fb, tiling); if (err < 0) return err; @@ -654,7 +656,7 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, * property in order to achieve the same result. The legacy BO flag * duplicates the DRM rotation property when both are set. */ - if (tegra_fb_is_bottom_up(state->fb)) + if (tegra_fb_is_bottom_up(new_plane_state->fb)) rotation |= DRM_MODE_REFLECT_Y; rotation = drm_rotation_simplify(rotation, supported_rotation); @@ -674,14 +676,14 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, * error out if the user tries to display a framebuffer with such a * configuration. */ - if (state->fb->format->num_planes > 2) { - if (state->fb->pitches[2] != state->fb->pitches[1]) { + if (new_plane_state->fb->format->num_planes > 2) { + if (new_plane_state->fb->pitches[2] != new_plane_state->fb->pitches[1]) { DRM_ERROR("unsupported UV-plane configuration\n"); return -EINVAL; } } - err = tegra_plane_state_add(tegra, state); + err = tegra_plane_state_add(tegra, new_plane_state); if (err < 0) return err; @@ -689,8 +691,10 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, } static void tegra_plane_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) + struct drm_atomic_state *state) { + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, + plane); struct tegra_plane *p = to_tegra_plane(plane); u32 value; @@ -704,42 +708,44 @@ static void tegra_plane_atomic_disable(struct drm_plane *plane, } static void tegra_plane_atomic_update(struct drm_plane *plane, - struct drm_plane_state *old_state) + struct drm_atomic_state *state) { - struct tegra_plane_state *state = to_tegra_plane_state(plane->state); - struct drm_framebuffer *fb = plane->state->fb; + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, + plane); + struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state); + struct drm_framebuffer *fb = new_state->fb; struct tegra_plane *p = to_tegra_plane(plane); struct tegra_dc_window window; unsigned int i; /* rien ne va plus */ - if (!plane->state->crtc || !plane->state->fb) + if (!new_state->crtc || !new_state->fb) return; - if (!plane->state->visible) - return tegra_plane_atomic_disable(plane, old_state); + if (!new_state->visible) + return tegra_plane_atomic_disable(plane, state); memset(&window, 0, sizeof(window)); - window.src.x = plane->state->src.x1 >> 16; - window.src.y = plane->state->src.y1 >> 16; - window.src.w = drm_rect_width(&plane->state->src) >> 16; - window.src.h = drm_rect_height(&plane->state->src) >> 16; - window.dst.x = plane->state->dst.x1; - window.dst.y = plane->state->dst.y1; - window.dst.w = drm_rect_width(&plane->state->dst); - window.dst.h = drm_rect_height(&plane->state->dst); + window.src.x = new_state->src.x1 >> 16; + window.src.y = new_state->src.y1 >> 16; + window.src.w = drm_rect_width(&new_state->src) >> 16; + window.src.h = drm_rect_height(&new_state->src) >> 16; + window.dst.x = new_state->dst.x1; + window.dst.y = new_state->dst.y1; + window.dst.w = drm_rect_width(&new_state->dst); + window.dst.h = drm_rect_height(&new_state->dst); window.bits_per_pixel = fb->format->cpp[0] * 8; - window.reflect_x = state->reflect_x; - window.reflect_y = state->reflect_y; + window.reflect_x = tegra_plane_state->reflect_x; + window.reflect_y = tegra_plane_state->reflect_y; /* copy from state */ - window.zpos = plane->state->normalized_zpos; - window.tiling = state->tiling; - window.format = state->format; - window.swap = state->swap; + window.zpos = new_state->normalized_zpos; + window.tiling = tegra_plane_state->tiling; + window.format = tegra_plane_state->format; + window.swap = tegra_plane_state->swap; for (i = 0; i < fb->format->num_planes; i++) { - window.base[i] = state->iova[i] + fb->offsets[i]; + window.base[i] = tegra_plane_state->iova[i] + fb->offsets[i]; /* * Tegra uses a shared stride for UV planes. Framebuffers are @@ -826,34 +832,40 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, return &plane->base; } -static const u32 tegra_cursor_plane_formats[] = { +static const u32 tegra_legacy_cursor_plane_formats[] = { DRM_FORMAT_RGBA8888, }; +static const u32 tegra_cursor_plane_formats[] = { + DRM_FORMAT_ARGB8888, +}; + static int tegra_cursor_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_atomic_state *state) { + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); struct tegra_plane *tegra = to_tegra_plane(plane); int err; /* no need for further checks if the plane is being disabled */ - if (!state->crtc) + if (!new_plane_state->crtc) return 0; /* scaling not supported for cursor */ - if ((state->src_w >> 16 != state->crtc_w) || - (state->src_h >> 16 != state->crtc_h)) + if ((new_plane_state->src_w >> 16 != new_plane_state->crtc_w) || + (new_plane_state->src_h >> 16 != new_plane_state->crtc_h)) return -EINVAL; /* only square cursors supported */ - if (state->src_w != state->src_h) + if (new_plane_state->src_w != new_plane_state->src_h) return -EINVAL; - if (state->crtc_w != 32 && state->crtc_w != 64 && - state->crtc_w != 128 && state->crtc_w != 256) + if (new_plane_state->crtc_w != 32 && new_plane_state->crtc_w != 64 && + new_plane_state->crtc_w != 128 && new_plane_state->crtc_w != 256) return -EINVAL; - err = tegra_plane_state_add(tegra, state); + err = tegra_plane_state_add(tegra, new_plane_state); if (err < 0) return err; @@ -861,17 +873,31 @@ 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 drm_atomic_state *state) { - struct tegra_plane_state *state = to_tegra_plane_state(plane->state); - struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); - u32 value = CURSOR_CLIP_DISPLAY; + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, + plane); + struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state); + struct tegra_dc *dc = to_tegra_dc(new_state->crtc); + struct tegra_drm *tegra = plane->dev->dev_private; +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + u64 dma_mask = *dc->dev->dma_mask; +#endif + unsigned int x, y; + u32 value = 0; /* rien ne va plus */ - if (!plane->state->crtc || !plane->state->fb) + if (!new_state->crtc || !new_state->fb) return; - switch (plane->state->crtc_w) { + /* + * Legacy display supports hardware clipping of the cursor, but + * nvdisplay relies on software to clip the cursor to the screen. + */ + if (!dc->soc->has_nvdisplay) + value |= CURSOR_CLIP_DISPLAY; + + switch (new_state->crtc_w) { case 32: value |= CURSOR_SIZE_32x32; break; @@ -890,15 +916,15 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane, default: WARN(1, "cursor size %ux%u not supported\n", - plane->state->crtc_w, plane->state->crtc_h); + new_state->crtc_w, new_state->crtc_h); return; } - value |= (state->iova[0] >> 10) & 0x3fffff; + value |= (tegra_plane_state->iova[0] >> 10) & 0x3fffff; tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR); #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT - value = (state->iova[0] >> 32) & 0x3; + value = (tegra_plane_state->iova[0] >> 32) & (dma_mask >> 32); tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI); #endif @@ -910,21 +936,47 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane, value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL); value &= ~CURSOR_DST_BLEND_MASK; value &= ~CURSOR_SRC_BLEND_MASK; - value |= CURSOR_MODE_NORMAL; + + if (dc->soc->has_nvdisplay) + value &= ~CURSOR_COMPOSITION_MODE_XOR; + else + value |= CURSOR_MODE_NORMAL; + value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC; value |= CURSOR_SRC_BLEND_K1_TIMES_SRC; value |= CURSOR_ALPHA; tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL); + /* nvdisplay relies on software for clipping */ + if (dc->soc->has_nvdisplay) { + struct drm_rect src; + + x = new_state->dst.x1; + y = new_state->dst.y1; + + drm_rect_fp_to_int(&src, &new_state->src); + + value = (src.y1 & tegra->vmask) << 16 | (src.x1 & tegra->hmask); + tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR); + + value = (drm_rect_height(&src) & tegra->vmask) << 16 | + (drm_rect_width(&src) & tegra->hmask); + tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR); + } else { + x = new_state->crtc_x; + y = new_state->crtc_y; + } + /* position the cursor */ - value = (plane->state->crtc_y & 0x3fff) << 16 | - (plane->state->crtc_x & 0x3fff); + value = ((y & tegra->vmask) << 16) | (x & tegra->hmask); tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION); } static void tegra_cursor_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) + struct drm_atomic_state *state) { + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, + plane); struct tegra_dc *dc; u32 value; @@ -970,8 +1022,13 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, plane->index = 6; plane->dc = dc; - num_formats = ARRAY_SIZE(tegra_cursor_plane_formats); - formats = tegra_cursor_plane_formats; + if (!dc->soc->has_nvdisplay) { + num_formats = ARRAY_SIZE(tegra_legacy_cursor_plane_formats); + formats = tegra_legacy_cursor_plane_formats; + } else { + num_formats = ARRAY_SIZE(tegra_cursor_plane_formats); + formats = tegra_cursor_plane_formats; + } err = drm_universal_plane_init(drm, &plane->base, possible_crtcs, &tegra_plane_funcs, formats, @@ -2023,6 +2080,16 @@ static bool tegra_dc_has_window_groups(struct tegra_dc *dc) return false; } +static int tegra_dc_early_init(struct host1x_client *client) +{ + struct drm_device *drm = dev_get_drvdata(client->host); + struct tegra_drm *tegra = drm->dev_private; + + tegra->num_crtcs++; + + return 0; +} + static int tegra_dc_init(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->host); @@ -2034,6 +2101,12 @@ static int tegra_dc_init(struct host1x_client *client) int err; /* + * DC has been reset by now, so VBLANK syncpoint can be released + * for general use. + */ + host1x_syncpt_release_vblank_reservation(client, 26 + dc->pipe); + + /* * 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. @@ -2099,6 +2172,12 @@ static int tegra_dc_init(struct host1x_client *client) if (dc->soc->pitch_align > tegra->pitch_align) tegra->pitch_align = dc->soc->pitch_align; + /* track maximum resolution */ + if (dc->soc->has_nvdisplay) + drm->mode_config.max_width = drm->mode_config.max_height = 16384; + else + drm->mode_config.max_width = drm->mode_config.max_height = 4096; + err = tegra_dc_rgb_init(drm, dc); if (err < 0 && err != -ENODEV) { dev_err(dc->dev, "failed to initialize RGB output: %d\n", err); @@ -2129,7 +2208,7 @@ cleanup: drm_plane_cleanup(primary); host1x_client_iommu_detach(client); - host1x_syncpt_free(dc->syncpt); + host1x_syncpt_put(dc->syncpt); return err; } @@ -2154,7 +2233,17 @@ static int tegra_dc_exit(struct host1x_client *client) } host1x_client_iommu_detach(client); - host1x_syncpt_free(dc->syncpt); + host1x_syncpt_put(dc->syncpt); + + return 0; +} + +static int tegra_dc_late_exit(struct host1x_client *client) +{ + struct drm_device *drm = dev_get_drvdata(client->host); + struct tegra_drm *tegra = drm->dev_private; + + tegra->num_crtcs--; return 0; } @@ -2223,8 +2312,10 @@ put_rpm: } static const struct host1x_client_ops dc_client_ops = { + .early_init = tegra_dc_early_init, .init = tegra_dc_init, .exit = tegra_dc_exit, + .late_exit = tegra_dc_late_exit, .suspend = tegra_dc_runtime_suspend, .resume = tegra_dc_runtime_resume, }; @@ -2234,6 +2325,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .supports_sector_layout = false, .has_legacy_blending = true, .pitch_align = 8, .has_powergate = false, @@ -2253,6 +2345,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .supports_sector_layout = false, .has_legacy_blending = true, .pitch_align = 8, .has_powergate = false, @@ -2272,6 +2365,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .supports_sector_layout = false, .has_legacy_blending = true, .pitch_align = 64, .has_powergate = true, @@ -2291,6 +2385,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .supports_sector_layout = false, .has_legacy_blending = false, .pitch_align = 64, .has_powergate = true, @@ -2310,6 +2405,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .supports_sector_layout = false, .has_legacy_blending = false, .pitch_align = 64, .has_powergate = true, @@ -2363,6 +2459,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .supports_sector_layout = false, .has_legacy_blending = false, .pitch_align = 64, .has_powergate = false, @@ -2411,6 +2508,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .supports_sector_layout = true, .has_legacy_blending = false, .pitch_align = 64, .has_powergate = false, @@ -2520,9 +2618,16 @@ static int tegra_dc_couple(struct tegra_dc *dc) static int tegra_dc_probe(struct platform_device *pdev) { + u64 dma_mask = dma_get_mask(pdev->dev.parent); struct tegra_dc *dc; int err; + err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask); + if (err < 0) { + dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err); + return err; + } + dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL); if (!dc) return -ENOMEM; diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 051d03dcb9b0..29f19c3c6149 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -52,6 +52,7 @@ struct tegra_dc_soc_info { bool supports_interlacing; bool supports_cursor; bool supports_block_linear; + bool supports_sector_layout; bool has_legacy_blending; unsigned int pitch_align; bool has_powergate; @@ -511,6 +512,8 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); #define DC_DISP_CURSOR_START_ADDR_HI 0x4ec #define DC_DISP_BLEND_CURSOR_CONTROL 0x4f1 +#define CURSOR_COMPOSITION_MODE_BLEND (0 << 25) +#define CURSOR_COMPOSITION_MODE_XOR (1 << 25) #define CURSOR_MODE_LEGACY (0 << 24) #define CURSOR_MODE_NORMAL (1 << 24) #define CURSOR_DST_BLEND_ZERO (0 << 16) @@ -705,6 +708,9 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); #define PROTOCOL_MASK (0xf << 8) #define PROTOCOL_SINGLE_TMDS_A (0x1 << 8) +#define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR 0x442 +#define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR 0x446 + #define DC_WIN_CORE_WINDOWGROUP_SET_CONTROL 0x702 #define OWNER_MASK (0xf << 0) #define OWNER(x) (((x) & 0xf) << 0) diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 105fb9cdbb3b..ea56c6ec25e4 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -534,9 +534,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev) dpaux->aux.transfer = tegra_dpaux_transfer; dpaux->aux.dev = &pdev->dev; - err = drm_dp_aux_register(&dpaux->aux); - if (err < 0) - return err; + drm_dp_aux_init(&dpaux->aux); /* * Assume that by default the DPAUX/I2C pads will be used for HDMI, @@ -589,8 +587,6 @@ static int tegra_dpaux_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - drm_dp_aux_unregister(&dpaux->aux); - mutex_lock(&dpaux_lock); list_del(&dpaux->list); mutex_unlock(&dpaux_lock); @@ -723,6 +719,10 @@ int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output) unsigned long timeout; int err; + err = drm_dp_aux_register(aux); + if (err < 0) + return err; + output->connector.polled = DRM_CONNECTOR_POLL_HPD; dpaux->output = output; @@ -760,6 +760,7 @@ int drm_dp_aux_detach(struct drm_dp_aux *aux) unsigned long timeout; int err; + drm_dp_aux_unregister(aux); disable_irq(dpaux->irq); if (dpaux->output->panel) { diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index e9ce7d6992d2..0c350b0daab4 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -65,11 +65,14 @@ static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state) struct tegra_drm *tegra = drm->dev_private; if (tegra->hub) { + bool fence_cookie = dma_fence_begin_signalling(); + drm_atomic_helper_commit_modeset_disables(drm, old_state); tegra_display_hub_atomic_commit(drm, old_state); drm_atomic_helper_commit_planes(drm, old_state, 0); drm_atomic_helper_commit_modeset_enables(drm, old_state); drm_atomic_helper_commit_hw_done(old_state); + dma_fence_end_signalling(fence_cookie); drm_atomic_helper_wait_for_vblanks(drm, old_state); drm_atomic_helper_cleanup_planes(drm, old_state); } else { @@ -171,7 +174,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, struct drm_tegra_syncpt syncpt; struct host1x *host1x = dev_get_drvdata(drm->dev->parent); struct drm_gem_object **refs; - struct host1x_syncpt *sp; + struct host1x_syncpt *sp = NULL; struct host1x_job *job; unsigned int num_refs; int err; @@ -298,8 +301,8 @@ int tegra_drm_submit(struct tegra_drm_context *context, goto fail; } - /* check whether syncpoint ID is valid */ - sp = host1x_syncpt_get(host1x, syncpt.id); + /* Syncpoint ref will be dropped on job release. */ + sp = host1x_syncpt_get_by_id(host1x, syncpt.id); if (!sp) { err = -ENOENT; goto fail; @@ -308,7 +311,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, job->is_addr_reg = context->client->ops->is_addr_reg; job->is_valid_class = context->client->ops->is_valid_class; job->syncpt_incrs = syncpt.incrs; - job->syncpt_id = syncpt.id; + job->syncpt = sp; job->timeout = 10000; if (args->timeout && args->timeout < 10000) @@ -380,7 +383,7 @@ static int tegra_syncpt_read(struct drm_device *drm, void *data, struct drm_tegra_syncpt_read *args = data; struct host1x_syncpt *sp; - sp = host1x_syncpt_get(host, args->id); + sp = host1x_syncpt_get_by_id_noref(host, args->id); if (!sp) return -EINVAL; @@ -395,7 +398,7 @@ static int tegra_syncpt_incr(struct drm_device *drm, void *data, struct drm_tegra_syncpt_incr *args = data; struct host1x_syncpt *sp; - sp = host1x_syncpt_get(host1x, args->id); + sp = host1x_syncpt_get_by_id_noref(host1x, args->id); if (!sp) return -EINVAL; @@ -409,7 +412,7 @@ static int tegra_syncpt_wait(struct drm_device *drm, void *data, struct drm_tegra_syncpt_wait *args = data; struct host1x_syncpt *sp; - sp = host1x_syncpt_get(host1x, args->id); + sp = host1x_syncpt_get_by_id_noref(host1x, args->id); if (!sp) return -EINVAL; @@ -1118,9 +1121,8 @@ static int host1x_drm_probe(struct host1x_device *dev) drm->mode_config.min_width = 0; drm->mode_config.min_height = 0; - - drm->mode_config.max_width = 4096; - drm->mode_config.max_height = 4096; + drm->mode_config.max_width = 0; + drm->mode_config.max_height = 0; drm->mode_config.allow_fb_modifiers = true; @@ -1139,6 +1141,14 @@ static int host1x_drm_probe(struct host1x_device *dev) if (err < 0) goto fbdev; + /* + * Now that all display controller have been initialized, the maximum + * supported resolution is known and the bitmask for horizontal and + * vertical bitfields can be computed. + */ + tegra->hmask = drm->mode_config.max_width - 1; + tegra->vmask = drm->mode_config.max_height - 1; + if (tegra->use_explicit_iommu) { u64 carveout_start, carveout_end, gem_start, gem_end; u64 dma_mask = dma_get_mask(&dev->dev); diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index f38de08e0c95..0cb868065348 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -24,6 +24,9 @@ #include "hub.h" #include "trace.h" +/* XXX move to include/uapi/drm/drm_fourcc.h? */ +#define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT_ULL(22) + struct reset_control; #ifdef CONFIG_DRM_FBDEV_EMULATION @@ -54,7 +57,9 @@ struct tegra_drm { struct tegra_fbdev *fbdev; #endif + unsigned int hmask, vmask; unsigned int pitch_align; + unsigned int num_crtcs; struct tegra_display_hub *hub; }; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 01939c57fc74..cae8b8cbe9dd 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -44,6 +44,15 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, { uint64_t modifier = framebuffer->modifier; + if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) { + if ((modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) == 0) + tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_TEGRA; + else + tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_GPU; + + modifier &= ~DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT; + } + switch (modifier) { case DRM_FORMAT_MOD_LINEAR: tiling->mode = TEGRA_BO_TILING_MODE_PITCH; @@ -86,6 +95,7 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, break; default: + DRM_DEBUG_KMS("unknown format modifier: %llx\n", modifier); return -EINVAL; } diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index fafb5724499b..c15fd99d6cb2 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h @@ -21,9 +21,15 @@ enum tegra_bo_tiling_mode { TEGRA_BO_TILING_MODE_BLOCK, }; +enum tegra_bo_sector_layout { + TEGRA_BO_SECTOR_LAYOUT_TEGRA, + TEGRA_BO_SECTOR_LAYOUT_GPU, +}; + struct tegra_bo_tiling { enum tegra_bo_tiling_mode mode; unsigned long value; + enum tegra_bo_sector_layout sector_layout; }; struct tegra_bo { diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index adbe2ddcda19..de288cba3905 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c @@ -67,7 +67,7 @@ static int gr2d_init(struct host1x_client *client) detach: host1x_client_iommu_detach(client); free: - host1x_syncpt_free(client->syncpts[0]); + host1x_syncpt_put(client->syncpts[0]); put: host1x_channel_put(gr2d->channel); return err; @@ -86,7 +86,7 @@ static int gr2d_exit(struct host1x_client *client) return err; host1x_client_iommu_detach(client); - host1x_syncpt_free(client->syncpts[0]); + host1x_syncpt_put(client->syncpts[0]); host1x_channel_put(gr2d->channel); return 0; diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index b0b8154e8104..24442ade0da3 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -76,7 +76,7 @@ static int gr3d_init(struct host1x_client *client) detach: host1x_client_iommu_detach(client); free: - host1x_syncpt_free(client->syncpts[0]); + host1x_syncpt_put(client->syncpts[0]); put: host1x_channel_put(gr3d->channel); return err; @@ -94,7 +94,7 @@ static int gr3d_exit(struct host1x_client *client) return err; host1x_client_iommu_detach(client); - host1x_syncpt_free(client->syncpts[0]); + host1x_syncpt_put(client->syncpts[0]); host1x_channel_put(gr3d->channel); return 0; diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index 5ce771cba133..bfae8a02f55b 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -55,6 +55,18 @@ static const u64 tegra_shared_plane_modifiers[] = { DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3), DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4), DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5), + /* + * The GPU sector layout is only supported on Tegra194, but these will + * be filtered out later on by ->format_mod_supported() on SoCs where + * it isn't supported. + */ + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, + /* sentinel */ DRM_FORMAT_MOD_INVALID }; @@ -336,25 +348,27 @@ static void tegra_dc_remove_shared_plane(struct tegra_dc *dc, } static int tegra_shared_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_atomic_state *state) { - struct tegra_plane_state *plane_state = to_tegra_plane_state(state); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); + struct tegra_plane_state *plane_state = to_tegra_plane_state(new_plane_state); struct tegra_shared_plane *tegra = to_tegra_shared_plane(plane); struct tegra_bo_tiling *tiling = &plane_state->tiling; - struct tegra_dc *dc = to_tegra_dc(state->crtc); + struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc); int err; /* no need for further checks if the plane is being disabled */ - if (!state->crtc || !state->fb) + if (!new_plane_state->crtc || !new_plane_state->fb) return 0; - err = tegra_plane_format(state->fb->format->format, + err = tegra_plane_format(new_plane_state->fb->format->format, &plane_state->format, &plane_state->swap); if (err < 0) return err; - err = tegra_fb_get_tiling(state->fb, tiling); + err = tegra_fb_get_tiling(new_plane_state->fb, tiling); if (err < 0) return err; @@ -364,13 +378,19 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane, return -EINVAL; } + if (tiling->sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU && + !dc->soc->supports_sector_layout) { + DRM_ERROR("hardware doesn't support GPU sector layout\n"); + return -EINVAL; + } + /* * Tegra doesn't support different strides for U and V planes so we * error out if the user tries to display a framebuffer with such a * configuration. */ - if (state->fb->format->num_planes > 2) { - if (state->fb->pitches[2] != state->fb->pitches[1]) { + if (new_plane_state->fb->format->num_planes > 2) { + if (new_plane_state->fb->pitches[2] != new_plane_state->fb->pitches[1]) { DRM_ERROR("unsupported UV-plane configuration\n"); return -EINVAL; } @@ -378,7 +398,7 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane, /* XXX scaling is not yet supported, add a check here */ - err = tegra_plane_state_add(&tegra->base, state); + err = tegra_plane_state_add(&tegra->base, new_plane_state); if (err < 0) return err; @@ -386,8 +406,10 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane, } static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) + struct drm_atomic_state *state) { + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, + plane); struct tegra_plane *p = to_tegra_plane(plane); struct tegra_dc *dc; u32 value; @@ -423,23 +445,25 @@ static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, } static void tegra_shared_plane_atomic_update(struct drm_plane *plane, - struct drm_plane_state *old_state) + struct drm_atomic_state *state) { - struct tegra_plane_state *state = to_tegra_plane_state(plane->state); - struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); - unsigned int zpos = plane->state->normalized_zpos; - struct drm_framebuffer *fb = plane->state->fb; + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, + plane); + struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state); + struct tegra_dc *dc = to_tegra_dc(new_state->crtc); + unsigned int zpos = new_state->normalized_zpos; + struct drm_framebuffer *fb = new_state->fb; struct tegra_plane *p = to_tegra_plane(plane); dma_addr_t base; u32 value; int err; /* rien ne va plus */ - if (!plane->state->crtc || !plane->state->fb) + if (!new_state->crtc || !new_state->fb) return; - if (!plane->state->visible) { - tegra_shared_plane_atomic_disable(plane, old_state); + if (!new_state->visible) { + tegra_shared_plane_atomic_disable(plane, state); return; } @@ -477,22 +501,32 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, /* disable compression */ tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL); - base = state->iova[0] + fb->offsets[0]; + base = tegra_plane_state->iova[0] + fb->offsets[0]; + +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + /* + * Physical address bit 39 in Tegra194 is used as a switch for special + * logic that swizzles the memory using either the legacy Tegra or the + * dGPU sector layout. + */ + if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU) + base |= BIT_ULL(39); +#endif - tegra_plane_writel(p, state->format, DC_WIN_COLOR_DEPTH); + tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH); tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS); - value = V_POSITION(plane->state->crtc_y) | - H_POSITION(plane->state->crtc_x); + value = V_POSITION(new_state->crtc_y) | + H_POSITION(new_state->crtc_x); tegra_plane_writel(p, value, DC_WIN_POSITION); - value = V_SIZE(plane->state->crtc_h) | H_SIZE(plane->state->crtc_w); + value = V_SIZE(new_state->crtc_h) | H_SIZE(new_state->crtc_w); tegra_plane_writel(p, value, DC_WIN_SIZE); value = WIN_ENABLE | COLOR_EXPAND; tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS); - value = V_SIZE(plane->state->crtc_h) | H_SIZE(plane->state->crtc_w); + value = V_SIZE(new_state->crtc_h) | H_SIZE(new_state->crtc_w); tegra_plane_writel(p, value, DC_WIN_CROPPED_SIZE); tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI); @@ -504,15 +538,15 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, value = CLAMP_BEFORE_BLEND | DEGAMMA_SRGB | INPUT_RANGE_FULL; tegra_plane_writel(p, value, DC_WIN_SET_PARAMS); - value = OFFSET_X(plane->state->src_y >> 16) | - OFFSET_Y(plane->state->src_x >> 16); + value = OFFSET_X(new_state->src_y >> 16) | + OFFSET_Y(new_state->src_x >> 16); tegra_plane_writel(p, value, DC_WINBUF_CROPPED_POINT); if (dc->soc->supports_block_linear) { - unsigned long height = state->tiling.value; + unsigned long height = tegra_plane_state->tiling.value; /* XXX */ - switch (state->tiling.mode) { + switch (tegra_plane_state->tiling.mode) { case TEGRA_BO_TILING_MODE_PITCH: value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(0) | DC_WINBUF_SURFACE_KIND_PITCH; @@ -556,9 +590,8 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY; struct tegra_drm *tegra = drm->dev_private; struct tegra_display_hub *hub = tegra->hub; - /* planes can be assigned to arbitrary CRTCs */ - unsigned int possible_crtcs = 0x7; struct tegra_shared_plane *plane; + unsigned int possible_crtcs; unsigned int num_formats; const u64 *modifiers; struct drm_plane *p; @@ -577,6 +610,9 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, p = &plane->base.base; + /* planes can be assigned to arbitrary CRTCs */ + possible_crtcs = BIT(tegra->num_crtcs) - 1; + num_formats = ARRAY_SIZE(tegra_shared_plane_formats); formats = tegra_shared_plane_formats; modifiers = tegra_shared_plane_modifiers; @@ -842,12 +878,19 @@ static const struct host1x_client_ops tegra_display_hub_ops = { static int tegra_display_hub_probe(struct platform_device *pdev) { + u64 dma_mask = dma_get_mask(pdev->dev.parent); struct device_node *child = NULL; struct tegra_display_hub *hub; struct clk *clk; unsigned int i; int err; + err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask); + if (err < 0) { + dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err); + return err; + } + hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL); if (!hub) return -ENOMEM; diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index 539d14935728..2e11b4b1f702 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -8,7 +8,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> -#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_plane_helper.h> #include "dc.h" @@ -83,6 +83,22 @@ static void tegra_plane_atomic_destroy_state(struct drm_plane *plane, kfree(state); } +static bool tegra_plane_supports_sector_layout(struct drm_plane *plane) +{ + struct drm_crtc *crtc; + + drm_for_each_crtc(crtc, plane->dev) { + if (plane->possible_crtcs & drm_crtc_mask(crtc)) { + struct tegra_dc *dc = to_tegra_dc(crtc); + + if (!dc->soc->supports_sector_layout) + return false; + } + } + + return true; +} + static bool tegra_plane_format_mod_supported(struct drm_plane *plane, uint32_t format, uint64_t modifier) @@ -92,6 +108,14 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane, if (modifier == DRM_FORMAT_MOD_LINEAR) return true; + /* check for the sector layout bit */ + if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) { + if (modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) { + if (!tegra_plane_supports_sector_layout(plane)) + return false; + } + } + if (info->num_planes == 1) return true; @@ -119,6 +143,14 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) dma_addr_t phys_addr, *phys; struct sg_table *sgt; + /* + * If we're not attached to a domain, we already stored the + * physical address when the buffer was allocated. If we're + * part of a group that's shared between all display + * controllers, we've also already mapped the framebuffer + * through the SMMU. In both cases we can short-circuit the + * code below and retrieve the stored IOV address. + */ if (!domain || dc->client.group) phys = &phys_addr; else @@ -198,7 +230,7 @@ int tegra_plane_prepare_fb(struct drm_plane *plane, if (!state->fb) return 0; - drm_gem_fb_prepare_fb(plane, state); + drm_gem_plane_helper_prepare_fb(plane, state); return tegra_dc_pin(dc, to_tegra_plane_state(state)); } diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 7b88261f57bb..0ea320c1092b 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -3125,21 +3125,21 @@ static int tegra_sor_init(struct host1x_client *client) if (err < 0) { dev_err(sor->dev, "failed to acquire SOR reset: %d\n", err); - return err; + goto rpm_put; } err = reset_control_assert(sor->rst); if (err < 0) { dev_err(sor->dev, "failed to assert SOR reset: %d\n", err); - return err; + goto rpm_put; } } err = clk_prepare_enable(sor->clk); if (err < 0) { dev_err(sor->dev, "failed to enable clock: %d\n", err); - return err; + goto rpm_put; } usleep_range(1000, 3000); @@ -3150,7 +3150,7 @@ static int tegra_sor_init(struct host1x_client *client) dev_err(sor->dev, "failed to deassert SOR reset: %d\n", err); clk_disable_unprepare(sor->clk); - return err; + goto rpm_put; } reset_control_release(sor->rst); @@ -3171,6 +3171,12 @@ static int tegra_sor_init(struct host1x_client *client) } return 0; + +rpm_put: + if (sor->rst) + pm_runtime_put(sor->dev); + + return err; } static int tegra_sor_exit(struct host1x_client *client) @@ -3739,12 +3745,8 @@ static int tegra_sor_probe(struct platform_device *pdev) if (!sor->aux) return -EPROBE_DEFER; - if (get_device(&sor->aux->ddc.dev)) { - if (try_module_get(sor->aux->ddc.owner)) - sor->output.ddc = &sor->aux->ddc; - else - put_device(&sor->aux->ddc.dev); - } + if (get_device(sor->aux->dev)) + sor->output.ddc = &sor->aux->ddc; } if (!sor->aux) { @@ -3772,12 +3774,13 @@ static int tegra_sor_probe(struct platform_device *pdev) err = tegra_sor_parse_dt(sor); if (err < 0) - return err; + goto put_aux; err = tegra_output_probe(&sor->output); - if (err < 0) - return dev_err_probe(&pdev->dev, err, - "failed to probe output\n"); + if (err < 0) { + dev_err_probe(&pdev->dev, err, "failed to probe output\n"); + goto put_aux; + } if (sor->ops && sor->ops->probe) { err = sor->ops->probe(sor); @@ -3916,17 +3919,10 @@ static int tegra_sor_probe(struct platform_device *pdev) platform_set_drvdata(pdev, sor); pm_runtime_enable(&pdev->dev); - INIT_LIST_HEAD(&sor->client.list); + host1x_client_init(&sor->client); sor->client.ops = &sor_client_ops; sor->client.dev = &pdev->dev; - err = host1x_client_register(&sor->client); - if (err < 0) { - dev_err(&pdev->dev, "failed to register host1x client: %d\n", - err); - goto rpm_disable; - } - /* * On Tegra210 and earlier, provide our own implementation for the * pad output clock. @@ -3938,13 +3934,13 @@ static int tegra_sor_probe(struct platform_device *pdev) sor->index); if (!name) { err = -ENOMEM; - goto unregister; + goto uninit; } err = host1x_client_resume(&sor->client); if (err < 0) { dev_err(sor->dev, "failed to resume: %d\n", err); - goto unregister; + goto uninit; } sor->clk_pad = tegra_clk_sor_pad_register(sor, name); @@ -3955,17 +3951,30 @@ static int tegra_sor_probe(struct platform_device *pdev) err = PTR_ERR(sor->clk_pad); dev_err(sor->dev, "failed to register SOR pad clock: %d\n", err); - goto unregister; + goto uninit; + } + + err = __host1x_client_register(&sor->client); + if (err < 0) { + dev_err(&pdev->dev, "failed to register host1x client: %d\n", + err); + goto uninit; } return 0; -unregister: - host1x_client_unregister(&sor->client); -rpm_disable: +uninit: + host1x_client_exit(&sor->client); pm_runtime_disable(&pdev->dev); remove: + if (sor->aux) + sor->output.ddc = NULL; + tegra_output_remove(&sor->output); +put_aux: + if (sor->aux) + put_device(sor->aux->dev); + return err; } @@ -3983,6 +3992,11 @@ static int tegra_sor_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); + if (sor->aux) { + put_device(sor->aux->dev); + sor->output.ddc = NULL; + } + tegra_output_remove(&sor->output); return 0; diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index 77e128832920..72aea1cc0cfa 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -214,7 +214,7 @@ static int vic_init(struct host1x_client *client) return 0; free_syncpt: - host1x_syncpt_free(client->syncpts[0]); + host1x_syncpt_put(client->syncpts[0]); free_channel: host1x_channel_put(vic->channel); detach: @@ -238,7 +238,7 @@ static int vic_exit(struct host1x_client *client) if (err < 0) return err; - host1x_syncpt_free(client->syncpts[0]); + host1x_syncpt_put(client->syncpts[0]); host1x_channel_put(vic->channel); host1x_client_iommu_detach(client); |