Merge remote-tracking branch 'airlied/drm-next' into drm-misc-next
Required for Daniel's drm_vblank_cleanup cleanup
This commit is contained in:
@@ -30,6 +30,7 @@ struct tegra_dc_soc_info {
|
||||
bool supports_block_linear;
|
||||
unsigned int pitch_align;
|
||||
bool has_powergate;
|
||||
bool broken_reset;
|
||||
};
|
||||
|
||||
struct tegra_plane {
|
||||
@@ -485,12 +486,25 @@ static int tegra_plane_state_add(struct tegra_plane *plane,
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct tegra_dc_state *tegra;
|
||||
struct drm_rect clip;
|
||||
int err;
|
||||
|
||||
/* Propagate errors from allocation or locking failures. */
|
||||
crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
clip.x1 = 0;
|
||||
clip.y1 = 0;
|
||||
clip.x2 = crtc_state->mode.hdisplay;
|
||||
clip.y2 = crtc_state->mode.vdisplay;
|
||||
|
||||
/* Check plane state for visibility and calculate clipping bounds */
|
||||
err = drm_plane_helper_check_state(state, &clip, 0, INT_MAX,
|
||||
true, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
tegra = to_dc_state(crtc_state);
|
||||
|
||||
tegra->planes |= WIN_A_ACT_REQ << plane->index;
|
||||
@@ -545,6 +559,23 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra_dc_disable_window(struct tegra_dc *dc, int index)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&dc->lock, flags);
|
||||
|
||||
value = WINDOW_A_SELECT << index;
|
||||
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
|
||||
|
||||
value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
|
||||
value &= ~WIN_ENABLE;
|
||||
tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
|
||||
|
||||
spin_unlock_irqrestore(&dc->lock, flags);
|
||||
}
|
||||
|
||||
static void tegra_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
@@ -559,15 +590,18 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
|
||||
if (!plane->state->crtc || !plane->state->fb)
|
||||
return;
|
||||
|
||||
if (!plane->state->visible)
|
||||
return tegra_dc_disable_window(dc, p->index);
|
||||
|
||||
memset(&window, 0, sizeof(window));
|
||||
window.src.x = plane->state->src_x >> 16;
|
||||
window.src.y = plane->state->src_y >> 16;
|
||||
window.src.w = plane->state->src_w >> 16;
|
||||
window.src.h = plane->state->src_h >> 16;
|
||||
window.dst.x = plane->state->crtc_x;
|
||||
window.dst.y = plane->state->crtc_y;
|
||||
window.dst.w = plane->state->crtc_w;
|
||||
window.dst.h = plane->state->crtc_h;
|
||||
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.bits_per_pixel = fb->format->cpp[0] * 8;
|
||||
window.bottom_up = tegra_fb_is_bottom_up(fb);
|
||||
|
||||
@@ -598,8 +632,6 @@ static void tegra_plane_atomic_disable(struct drm_plane *plane,
|
||||
{
|
||||
struct tegra_plane *p = to_tegra_plane(plane);
|
||||
struct tegra_dc *dc;
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
/* rien ne va plus */
|
||||
if (!old_state || !old_state->crtc)
|
||||
@@ -607,16 +639,7 @@ static void tegra_plane_atomic_disable(struct drm_plane *plane,
|
||||
|
||||
dc = to_tegra_dc(old_state->crtc);
|
||||
|
||||
spin_lock_irqsave(&dc->lock, flags);
|
||||
|
||||
value = WINDOW_A_SELECT << p->index;
|
||||
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
|
||||
|
||||
value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
|
||||
value &= ~WIN_ENABLE;
|
||||
tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
|
||||
|
||||
spin_unlock_irqrestore(&dc->lock, flags);
|
||||
tegra_dc_disable_window(dc, p->index);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs tegra_primary_plane_helper_funcs = {
|
||||
@@ -1856,6 +1879,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
|
||||
.supports_block_linear = false,
|
||||
.pitch_align = 8,
|
||||
.has_powergate = false,
|
||||
.broken_reset = true,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
|
||||
@@ -1865,6 +1889,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
|
||||
.supports_block_linear = false,
|
||||
.pitch_align = 8,
|
||||
.has_powergate = false,
|
||||
.broken_reset = false,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
|
||||
@@ -1874,6 +1899,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
|
||||
.supports_block_linear = false,
|
||||
.pitch_align = 64,
|
||||
.has_powergate = true,
|
||||
.broken_reset = false,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
|
||||
@@ -1883,6 +1909,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
|
||||
.supports_block_linear = true,
|
||||
.pitch_align = 64,
|
||||
.has_powergate = true,
|
||||
.broken_reset = false,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
|
||||
@@ -1892,6 +1919,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
|
||||
.supports_block_linear = true,
|
||||
.pitch_align = 64,
|
||||
.has_powergate = true,
|
||||
.broken_reset = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_dc_of_match[] = {
|
||||
@@ -1989,7 +2017,8 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(dc->rst);
|
||||
}
|
||||
|
||||
reset_control_assert(dc->rst);
|
||||
if (!dc->soc->broken_reset)
|
||||
reset_control_assert(dc->rst);
|
||||
|
||||
if (dc->soc->has_powergate) {
|
||||
if (dc->pipe == 0)
|
||||
@@ -2063,10 +2092,12 @@ static int tegra_dc_suspend(struct device *dev)
|
||||
struct tegra_dc *dc = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = reset_control_assert(dc->rst);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to assert reset: %d\n", err);
|
||||
return err;
|
||||
if (!dc->soc->broken_reset) {
|
||||
err = reset_control_assert(dc->rst);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to assert reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (dc->soc->has_powergate)
|
||||
@@ -2096,10 +2127,13 @@ static int tegra_dc_resume(struct device *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = reset_control_deassert(dc->rst);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to deassert reset: %d\n", err);
|
||||
return err;
|
||||
if (!dc->soc->broken_reset) {
|
||||
err = reset_control_deassert(dc->rst);
|
||||
if (err < 0) {
|
||||
dev_err(dev,
|
||||
"failed to deassert reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#define CARVEOUT_SZ SZ_64M
|
||||
#define CDMA_GATHER_FETCHES_MAX_NB 16383
|
||||
|
||||
struct tegra_drm_file {
|
||||
struct idr contexts;
|
||||
@@ -345,6 +346,36 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int host1x_waitchk_copy_from_user(struct host1x_waitchk *dest,
|
||||
struct drm_tegra_waitchk __user *src,
|
||||
struct drm_file *file)
|
||||
{
|
||||
u32 cmdbuf;
|
||||
int err;
|
||||
|
||||
err = get_user(cmdbuf, &src->handle);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = get_user(dest->offset, &src->offset);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = get_user(dest->syncpt_id, &src->syncpt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = get_user(dest->thresh, &src->thresh);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dest->bo = host1x_bo_lookup(file, cmdbuf);
|
||||
if (!dest->bo)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
struct drm_tegra_submit *args, struct drm_device *drm,
|
||||
struct drm_file *file)
|
||||
@@ -359,6 +390,8 @@ int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
struct drm_tegra_waitchk __user *waitchks =
|
||||
(void __user *)(uintptr_t)args->waitchks;
|
||||
struct drm_tegra_syncpt syncpt;
|
||||
struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
|
||||
struct host1x_syncpt *sp;
|
||||
struct host1x_job *job;
|
||||
int err;
|
||||
|
||||
@@ -366,6 +399,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
if (args->num_syncpts != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* We don't yet support waitchks */
|
||||
if (args->num_waitchks != 0)
|
||||
return -EINVAL;
|
||||
|
||||
job = host1x_job_alloc(context->channel, args->num_cmdbufs,
|
||||
args->num_relocs, args->num_waitchks);
|
||||
if (!job)
|
||||
@@ -380,18 +417,42 @@ int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
while (num_cmdbufs) {
|
||||
struct drm_tegra_cmdbuf cmdbuf;
|
||||
struct host1x_bo *bo;
|
||||
struct tegra_bo *obj;
|
||||
u64 offset;
|
||||
|
||||
if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) {
|
||||
err = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* The maximum number of CDMA gather fetches is 16383, a higher
|
||||
* value means the words count is malformed.
|
||||
*/
|
||||
if (cmdbuf.words > CDMA_GATHER_FETCHES_MAX_NB) {
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bo = host1x_bo_lookup(file, cmdbuf.handle);
|
||||
if (!bo) {
|
||||
err = -ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32);
|
||||
obj = host1x_to_tegra_bo(bo);
|
||||
|
||||
/*
|
||||
* Gather buffer base address must be 4-bytes aligned,
|
||||
* unaligned offset is malformed and cause commands stream
|
||||
* corruption on the buffer address relocation.
|
||||
*/
|
||||
if (offset & 3 || offset >= obj->gem.size) {
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
|
||||
num_cmdbufs--;
|
||||
cmdbufs++;
|
||||
@@ -399,17 +460,59 @@ int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
|
||||
/* copy and resolve relocations from submit */
|
||||
while (num_relocs--) {
|
||||
struct host1x_reloc *reloc;
|
||||
struct tegra_bo *obj;
|
||||
|
||||
err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs],
|
||||
&relocs[num_relocs], drm,
|
||||
file);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
reloc = &job->relocarray[num_relocs];
|
||||
obj = host1x_to_tegra_bo(reloc->cmdbuf.bo);
|
||||
|
||||
/*
|
||||
* The unaligned cmdbuf offset will cause an unaligned write
|
||||
* during of the relocations patching, corrupting the commands
|
||||
* stream.
|
||||
*/
|
||||
if (reloc->cmdbuf.offset & 3 ||
|
||||
reloc->cmdbuf.offset >= obj->gem.size) {
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
obj = host1x_to_tegra_bo(reloc->target.bo);
|
||||
|
||||
if (reloc->target.offset >= obj->gem.size) {
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_from_user(job->waitchk, waitchks,
|
||||
sizeof(*waitchks) * num_waitchks)) {
|
||||
err = -EFAULT;
|
||||
goto fail;
|
||||
/* copy and resolve waitchks from submit */
|
||||
while (num_waitchks--) {
|
||||
struct host1x_waitchk *wait = &job->waitchk[num_waitchks];
|
||||
struct tegra_bo *obj;
|
||||
|
||||
err = host1x_waitchk_copy_from_user(wait,
|
||||
&waitchks[num_waitchks],
|
||||
file);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
obj = host1x_to_tegra_bo(wait->bo);
|
||||
|
||||
/*
|
||||
* The unaligned offset will cause an unaligned write during
|
||||
* of the waitchks patching, corrupting the commands stream.
|
||||
*/
|
||||
if (wait->offset & 3 ||
|
||||
wait->offset >= obj->gem.size) {
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts,
|
||||
@@ -418,7 +521,15 @@ int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* check whether syncpoint ID is valid */
|
||||
sp = host1x_syncpt_get(host1x, syncpt.id);
|
||||
if (!sp) {
|
||||
err = -ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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->timeout = 10000;
|
||||
@@ -448,18 +559,6 @@ fail:
|
||||
|
||||
|
||||
#ifdef CONFIG_DRM_TEGRA_STAGING
|
||||
static struct tegra_drm_context *
|
||||
tegra_drm_file_get_context(struct tegra_drm_file *file, u32 id)
|
||||
{
|
||||
struct tegra_drm_context *context;
|
||||
|
||||
mutex_lock(&file->lock);
|
||||
context = idr_find(&file->contexts, id);
|
||||
mutex_unlock(&file->lock);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static int tegra_gem_create(struct drm_device *drm, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
@@ -548,7 +647,7 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = idr_alloc(&fpriv->contexts, context, 0, 0, GFP_KERNEL);
|
||||
err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
client->ops->close_channel(context);
|
||||
return err;
|
||||
@@ -603,7 +702,7 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
|
||||
|
||||
mutex_lock(&fpriv->lock);
|
||||
|
||||
context = tegra_drm_file_get_context(fpriv, args->context);
|
||||
context = idr_find(&fpriv->contexts, args->context);
|
||||
if (!context) {
|
||||
err = -EINVAL;
|
||||
goto unlock;
|
||||
@@ -628,7 +727,7 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
|
||||
|
||||
mutex_lock(&fpriv->lock);
|
||||
|
||||
context = tegra_drm_file_get_context(fpriv, args->context);
|
||||
context = idr_find(&fpriv->contexts, args->context);
|
||||
if (!context) {
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
@@ -657,7 +756,7 @@ static int tegra_submit(struct drm_device *drm, void *data,
|
||||
|
||||
mutex_lock(&fpriv->lock);
|
||||
|
||||
context = tegra_drm_file_get_context(fpriv, args->context);
|
||||
context = idr_find(&fpriv->contexts, args->context);
|
||||
if (!context) {
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
@@ -682,7 +781,7 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
|
||||
|
||||
mutex_lock(&fpriv->lock);
|
||||
|
||||
context = tegra_drm_file_get_context(fpriv, args->context);
|
||||
context = idr_find(&fpriv->contexts, args->context);
|
||||
if (!context) {
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
|
@@ -83,6 +83,7 @@ struct tegra_drm_client_ops {
|
||||
struct tegra_drm_context *context);
|
||||
void (*close_channel)(struct tegra_drm_context *context);
|
||||
int (*is_addr_reg)(struct device *dev, u32 class, u32 offset);
|
||||
int (*is_valid_class)(u32 class);
|
||||
int (*submit)(struct tegra_drm_context *context,
|
||||
struct drm_tegra_submit *args, struct drm_device *drm,
|
||||
struct drm_file *file);
|
||||
|
@@ -20,11 +20,6 @@
|
||||
#include "drm.h"
|
||||
#include "gem.h"
|
||||
|
||||
static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
|
||||
{
|
||||
return container_of(bo, struct tegra_bo, base);
|
||||
}
|
||||
|
||||
static void tegra_bo_put(struct host1x_bo *bo)
|
||||
{
|
||||
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
|
||||
|
@@ -52,6 +52,11 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
|
||||
return container_of(gem, struct tegra_bo, gem);
|
||||
}
|
||||
|
||||
static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
|
||||
{
|
||||
return container_of(bo, struct tegra_bo, base);
|
||||
}
|
||||
|
||||
struct tegra_bo *tegra_bo_create(struct drm_device *drm, size_t size,
|
||||
unsigned long flags);
|
||||
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
|
||||
|
@@ -38,7 +38,7 @@ static int gr2d_init(struct host1x_client *client)
|
||||
|
||||
client->syncpts[0] = host1x_syncpt_request(client->dev, flags);
|
||||
if (!client->syncpts[0]) {
|
||||
host1x_channel_free(gr2d->channel);
|
||||
host1x_channel_put(gr2d->channel);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ static int gr2d_exit(struct host1x_client *client)
|
||||
return err;
|
||||
|
||||
host1x_syncpt_free(client->syncpts[0]);
|
||||
host1x_channel_free(gr2d->channel);
|
||||
host1x_channel_put(gr2d->channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -109,10 +109,17 @@ static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gr2d_is_valid_class(u32 class)
|
||||
{
|
||||
return (class == HOST1X_CLASS_GR2D ||
|
||||
class == HOST1X_CLASS_GR2D_SB);
|
||||
}
|
||||
|
||||
static const struct tegra_drm_client_ops gr2d_ops = {
|
||||
.open_channel = gr2d_open_channel,
|
||||
.close_channel = gr2d_close_channel,
|
||||
.is_addr_reg = gr2d_is_addr_reg,
|
||||
.is_valid_class = gr2d_is_valid_class,
|
||||
.submit = tegra_drm_submit,
|
||||
};
|
||||
|
||||
|
@@ -48,7 +48,7 @@ static int gr3d_init(struct host1x_client *client)
|
||||
|
||||
client->syncpts[0] = host1x_syncpt_request(client->dev, flags);
|
||||
if (!client->syncpts[0]) {
|
||||
host1x_channel_free(gr3d->channel);
|
||||
host1x_channel_put(gr3d->channel);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ static int gr3d_exit(struct host1x_client *client)
|
||||
return err;
|
||||
|
||||
host1x_syncpt_free(client->syncpts[0]);
|
||||
host1x_channel_free(gr3d->channel);
|
||||
host1x_channel_put(gr3d->channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -182,7 +182,7 @@ static int vic_init(struct host1x_client *client)
|
||||
free_syncpt:
|
||||
host1x_syncpt_free(client->syncpts[0]);
|
||||
free_channel:
|
||||
host1x_channel_free(vic->channel);
|
||||
host1x_channel_put(vic->channel);
|
||||
detach_device:
|
||||
if (tegra->domain)
|
||||
iommu_detach_device(tegra->domain, vic->dev);
|
||||
@@ -203,7 +203,7 @@ static int vic_exit(struct host1x_client *client)
|
||||
return err;
|
||||
|
||||
host1x_syncpt_free(client->syncpts[0]);
|
||||
host1x_channel_free(vic->channel);
|
||||
host1x_channel_put(vic->channel);
|
||||
|
||||
if (vic->domain) {
|
||||
iommu_detach_device(vic->domain, vic->dev);
|
||||
|
Reference in New Issue
Block a user