diff options
30 files changed, 370 insertions, 465 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d037504a5748..4df83ffa5c1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6933,6 +6933,7 @@ F: drivers/phy/mediatek/phy-mtk-mipi* DRM DRIVERS FOR NVIDIA TEGRA M: Thierry Reding <thierry.reding@gmail.com> +M: Mikko Perttunen <mperttunen@nvidia.com> L: dri-devel@lists.freedesktop.org L: linux-tegra@vger.kernel.org S: Supported diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index c36323f1c7e6..56453ca277c2 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_TEGRA tristate "NVIDIA Tegra DRM" - depends on ARCH_TEGRA || (ARM && COMPILE_TEST) + depends on ARCH_TEGRA || COMPILE_TEST depends on COMMON_CLK depends on DRM depends on OF diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile index bb0d2c144b55..6fc4b504e786 100644 --- a/drivers/gpu/drm/tegra/Makefile +++ b/drivers/gpu/drm/tegra/Makefile @@ -29,4 +29,6 @@ tegra-drm-y := \ tegra-drm-y += trace.o +tegra-drm-$(CONFIG_DRM_FBDEV_EMULATION) += fbdev.o + obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index a67453cee883..6e78416e64b0 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -2381,7 +2381,6 @@ static int tegra_crtc_calculate_memory_bandwidth(struct drm_crtc *crtc, const struct tegra_plane_state *tegra_state; const struct drm_plane_state *plane_state; struct tegra_dc *dc = to_tegra_dc(crtc); - const struct drm_crtc_state *old_state; struct drm_crtc_state *new_state; struct tegra_plane *tegra; struct drm_plane *plane; @@ -2396,7 +2395,6 @@ static int tegra_crtc_calculate_memory_bandwidth(struct drm_crtc *crtc, return 0; new_state = drm_atomic_get_new_crtc_state(state, crtc); - old_state = drm_atomic_get_old_crtc_state(state, crtc); /* * For overlapping planes pixel's data is fetched for each plane at @@ -3263,27 +3261,15 @@ disable_pm: return err; } -static int tegra_dc_remove(struct platform_device *pdev) +static void tegra_dc_remove(struct platform_device *pdev) { struct tegra_dc *dc = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&dc->client); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } + host1x_client_unregister(&dc->client); - err = tegra_dc_rgb_remove(dc); - if (err < 0) { - dev_err(&pdev->dev, "failed to remove RGB output: %d\n", err); - return err; - } + tegra_dc_rgb_remove(dc); pm_runtime_disable(&pdev->dev); - - return 0; } struct platform_driver tegra_dc_driver = { @@ -3292,5 +3278,5 @@ struct platform_driver tegra_dc_driver = { .of_match_table = tegra_dc_of_match, }, .probe = tegra_dc_probe, - .remove = tegra_dc_remove, + .remove_new = tegra_dc_remove, }; diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index f902794d42cc..0559fa6b1bf7 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -169,7 +169,7 @@ void tegra_crtc_atomic_post_commit(struct drm_crtc *crtc, /* from rgb.c */ int tegra_dc_rgb_probe(struct tegra_dc *dc); -int tegra_dc_rgb_remove(struct tegra_dc *dc); +void tegra_dc_rgb_remove(struct tegra_dc *dc); int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc); int tegra_dc_rgb_exit(struct tegra_dc *dc); diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 3c84e73d5051..4d2677dcd831 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -579,7 +579,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev) return 0; } -static int tegra_dpaux_remove(struct platform_device *pdev) +static void tegra_dpaux_remove(struct platform_device *pdev) { struct tegra_dpaux *dpaux = platform_get_drvdata(pdev); @@ -594,8 +594,6 @@ static int tegra_dpaux_remove(struct platform_device *pdev) mutex_lock(&dpaux_lock); list_del(&dpaux->list); mutex_unlock(&dpaux_lock); - - return 0; } static int tegra_dpaux_suspend(struct device *dev) @@ -695,7 +693,7 @@ struct platform_driver tegra_dpaux_driver = { .pm = pm_ptr(&tegra_dpaux_pm_ops), }, .probe = tegra_dpaux_probe, - .remove = tegra_dpaux_remove, + .remove_new = tegra_dpaux_remove, }; struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 6ca9f396e55b..85ba96cddd51 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -56,9 +56,6 @@ static int tegra_atomic_check(struct drm_device *drm, static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = { .fb_create = tegra_fb_create, -#ifdef CONFIG_DRM_FBDEV_EMULATION - .output_poll_changed = drm_fb_helper_output_poll_changed, -#endif .atomic_check = tegra_atomic_check, .atomic_commit = drm_atomic_helper_commit, }; @@ -885,7 +882,6 @@ static const struct drm_driver tegra_drm_driver = { DRIVER_ATOMIC | DRIVER_RENDER | DRIVER_SYNCOBJ, .open = tegra_drm_open, .postclose = tegra_drm_postclose, - .lastclose = drm_fb_helper_lastclose, #if defined(CONFIG_DEBUG_FS) .debugfs_init = tegra_debugfs_init, @@ -1185,15 +1181,11 @@ static int host1x_drm_probe(struct host1x_device *dev) drm->mode_config.funcs = &tegra_drm_mode_config_funcs; drm->mode_config.helper_private = &tegra_drm_mode_config_helpers; - err = tegra_drm_fb_prepare(drm); - if (err < 0) - goto config; - drm_kms_helper_poll_init(drm); err = host1x_device_init(dev); if (err < 0) - goto fbdev; + goto poll; /* * Now that all display controller have been initialized, the maximum @@ -1256,18 +1248,14 @@ static int host1x_drm_probe(struct host1x_device *dev) if (err < 0) goto hub; - err = tegra_drm_fb_init(drm); + err = drm_dev_register(drm, 0); if (err < 0) goto hub; - err = drm_dev_register(drm, 0); - if (err < 0) - goto fb; + tegra_fbdev_setup(drm); return 0; -fb: - tegra_drm_fb_exit(drm); hub: if (tegra->hub) tegra_display_hub_cleanup(tegra->hub); @@ -1280,10 +1268,8 @@ device: } host1x_device_exit(dev); -fbdev: +poll: drm_kms_helper_poll_fini(drm); - tegra_drm_fb_free(drm); -config: drm_mode_config_cleanup(drm); domain: if (tegra->domain) @@ -1304,7 +1290,6 @@ static int host1x_drm_remove(struct host1x_device *dev) drm_dev_unregister(drm); drm_kms_helper_poll_fini(drm); - tegra_drm_fb_exit(drm); drm_atomic_helper_shutdown(drm); drm_mode_config_cleanup(drm); diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 845e60f144c7..f9d18e8cf6ab 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -15,7 +15,6 @@ #include <drm/drm_bridge.h> #include <drm/drm_edid.h> #include <drm/drm_encoder.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_fixed.h> #include <drm/drm_probe_helper.h> #include <uapi/drm/tegra_drm.h> @@ -29,13 +28,6 @@ struct reset_control; -#ifdef CONFIG_DRM_FBDEV_EMULATION -struct tegra_fbdev { - struct drm_fb_helper base; - struct drm_framebuffer *fb; -}; -#endif - struct tegra_drm { struct drm_device *drm; @@ -53,10 +45,6 @@ struct tegra_drm { struct mutex clients_lock; struct list_head clients; -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct tegra_fbdev *fbdev; -#endif - unsigned int hmask, vmask; unsigned int pitch_align; unsigned int num_crtcs; @@ -196,13 +184,20 @@ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, struct tegra_bo_tiling *tiling); +struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct tegra_bo **planes, + unsigned int num_planes); struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, struct drm_file *file, const struct drm_mode_fb_cmd2 *cmd); -int tegra_drm_fb_prepare(struct drm_device *drm); -void tegra_drm_fb_free(struct drm_device *drm); -int tegra_drm_fb_init(struct drm_device *drm); -void tegra_drm_fb_exit(struct drm_device *drm); + +#ifdef CONFIG_DRM_FBDEV_EMULATION +void tegra_fbdev_setup(struct drm_device *drm); +#else +static inline void tegra_fbdev_setup(struct drm_device *drm) +{ } +#endif extern struct platform_driver tegra_display_hub_driver; extern struct platform_driver tegra_dc_driver; diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index de1333dc0d86..a9870c828374 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -912,6 +912,15 @@ static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) u32 value; int err; + /* If the bootloader enabled DSI it needs to be disabled + * in order for the panel initialization commands to be + * properly sent. + */ + value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); + + if (value & DSI_POWER_CONTROL_ENABLE) + tegra_dsi_disable(dsi); + err = tegra_dsi_prepare(dsi); if (err < 0) { dev_err(dsi->dev, "failed to prepare: %d\n", err); @@ -1589,28 +1598,24 @@ static int tegra_dsi_probe(struct platform_device *pdev) } dsi->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(dsi->clk)) { - dev_err(&pdev->dev, "cannot get DSI clock\n"); - return PTR_ERR(dsi->clk); - } + if (IS_ERR(dsi->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk), + "cannot get DSI clock\n"); dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); - if (IS_ERR(dsi->clk_lp)) { - dev_err(&pdev->dev, "cannot get low-power clock\n"); - return PTR_ERR(dsi->clk_lp); - } + if (IS_ERR(dsi->clk_lp)) + return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_lp), + "cannot get low-power clock\n"); dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); - if (IS_ERR(dsi->clk_parent)) { - dev_err(&pdev->dev, "cannot get parent clock\n"); - return PTR_ERR(dsi->clk_parent); - } + if (IS_ERR(dsi->clk_parent)) + return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_parent), + "cannot get parent clock\n"); dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); - if (IS_ERR(dsi->vdd)) { - dev_err(&pdev->dev, "cannot get VDD supply\n"); - return PTR_ERR(dsi->vdd); - } + if (IS_ERR(dsi->vdd)) + return dev_err_probe(&pdev->dev, PTR_ERR(dsi->vdd), + "cannot get VDD supply\n"); err = tegra_dsi_setup_clocks(dsi); if (err < 0) { @@ -1659,26 +1664,18 @@ mipi_free: return err; } -static int tegra_dsi_remove(struct platform_device *pdev) +static void tegra_dsi_remove(struct platform_device *pdev) { struct tegra_dsi *dsi = platform_get_drvdata(pdev); - int err; pm_runtime_disable(&pdev->dev); - err = host1x_client_unregister(&dsi->client); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } + host1x_client_unregister(&dsi->client); tegra_output_remove(&dsi->output); mipi_dsi_host_unregister(&dsi->host); tegra_mipi_free(dsi->mipi); - - return 0; } static const struct of_device_id tegra_dsi_of_match[] = { @@ -1696,5 +1693,5 @@ struct platform_driver tegra_dsi_driver = { .of_match_table = tegra_dsi_of_match, }, .probe = tegra_dsi_probe, - .remove = tegra_dsi_remove, + .remove_new = tegra_dsi_remove, }; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index bfebe2786d61..a719af1dc9a5 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -17,13 +17,6 @@ #include "drm.h" #include "gem.h" -#ifdef CONFIG_DRM_FBDEV_EMULATION -static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper) -{ - return container_of(helper, struct tegra_fbdev, base); -} -#endif - struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, unsigned int index) { @@ -108,10 +101,10 @@ static const struct drm_framebuffer_funcs tegra_fb_funcs = { .create_handle = drm_gem_fb_create_handle, }; -static struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct tegra_bo **planes, - unsigned int num_planes) +struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct tegra_bo **planes, + unsigned int num_planes) { struct drm_framebuffer *fb; unsigned int i; @@ -186,230 +179,3 @@ unreference: return ERR_PTR(err); } - -#ifdef CONFIG_DRM_FBDEV_EMULATION -static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct drm_fb_helper *helper = info->par; - struct tegra_bo *bo; - int err; - - bo = tegra_fb_get_plane(helper->fb, 0); - - err = drm_gem_mmap_obj(&bo->gem, bo->gem.size, vma); - if (err < 0) - return err; - - return __tegra_gem_mmap(&bo->gem, vma); -} - -static const struct fb_ops tegra_fb_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_read = drm_fb_helper_sys_read, - .fb_write = drm_fb_helper_sys_write, - .fb_fillrect = drm_fb_helper_sys_fillrect, - .fb_copyarea = drm_fb_helper_sys_copyarea, - .fb_imageblit = drm_fb_helper_sys_imageblit, - .fb_mmap = tegra_fb_mmap, -}; - -static int tegra_fbdev_probe(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); - struct tegra_drm *tegra = helper->dev->dev_private; - struct drm_device *drm = helper->dev; - struct drm_mode_fb_cmd2 cmd = { 0 }; - unsigned int bytes_per_pixel; - struct drm_framebuffer *fb; - unsigned long offset; - struct fb_info *info; - struct tegra_bo *bo; - size_t size; - int err; - - bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); - - cmd.width = sizes->surface_width; - cmd.height = sizes->surface_height; - cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, - tegra->pitch_align); - - cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - size = cmd.pitches[0] * cmd.height; - - bo = tegra_bo_create(drm, size, 0); - if (IS_ERR(bo)) - return PTR_ERR(bo); - - info = drm_fb_helper_alloc_info(helper); - if (IS_ERR(info)) { - dev_err(drm->dev, "failed to allocate framebuffer info\n"); - drm_gem_object_put(&bo->gem); - return PTR_ERR(info); - } - - fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1); - if (IS_ERR(fbdev->fb)) { - err = PTR_ERR(fbdev->fb); - dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", - err); - drm_gem_object_put(&bo->gem); - return PTR_ERR(fbdev->fb); - } - - fb = fbdev->fb; - helper->fb = fb; - helper->info = info; - - info->fbops = &tegra_fb_ops; - - drm_fb_helper_fill_info(info, helper, sizes); - - offset = info->var.xoffset * bytes_per_pixel + - info->var.yoffset * fb->pitches[0]; - - if (bo->pages) { - bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP, - pgprot_writecombine(PAGE_KERNEL)); - if (!bo->vaddr) { - dev_err(drm->dev, "failed to vmap() framebuffer\n"); - err = -ENOMEM; - goto destroy; - } - } - - info->screen_base = (void __iomem *)bo->vaddr + offset; - info->screen_size = size; - info->fix.smem_start = (unsigned long)(bo->iova + offset); - info->fix.smem_len = size; - - return 0; - -destroy: - drm_framebuffer_remove(fb); - return err; -} - -static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = { - .fb_probe = tegra_fbdev_probe, -}; - -static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm) -{ - struct tegra_fbdev *fbdev; - - fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); - if (!fbdev) { - dev_err(drm->dev, "failed to allocate DRM fbdev\n"); - return ERR_PTR(-ENOMEM); - } - - drm_fb_helper_prepare(drm, &fbdev->base, 32, &tegra_fb_helper_funcs); - - return fbdev; -} - -static void tegra_fbdev_free(struct tegra_fbdev *fbdev) -{ - drm_fb_helper_unprepare(&fbdev->base); - kfree(fbdev); -} - -static int tegra_fbdev_init(struct tegra_fbdev *fbdev, - unsigned int num_crtc, - unsigned int max_connectors) -{ - struct drm_device *drm = fbdev->base.dev; - int err; - - err = drm_fb_helper_init(drm, &fbdev->base); - if (err < 0) { - dev_err(drm->dev, "failed to initialize DRM FB helper: %d\n", - err); - return err; - } - - err = drm_fb_helper_initial_config(&fbdev->base); - if (err < 0) { - dev_err(drm->dev, "failed to set initial configuration: %d\n", - err); - goto fini; - } - - return 0; - -fini: - drm_fb_helper_fini(&fbdev->base); - return err; -} - -static void tegra_fbdev_exit(struct tegra_fbdev *fbdev) -{ - drm_fb_helper_unregister_info(&fbdev->base); - - if (fbdev->fb) { - struct tegra_bo *bo = tegra_fb_get_plane(fbdev->fb, 0); - - /* Undo the special mapping we made in fbdev probe. */ - if (bo && bo->pages) { - vunmap(bo->vaddr); - bo->vaddr = NULL; - } - - drm_framebuffer_remove(fbdev->fb); - } - - drm_fb_helper_fini(&fbdev->base); - tegra_fbdev_free(fbdev); -} -#endif - -int tegra_drm_fb_prepare(struct drm_device *drm) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct tegra_drm *tegra = drm->dev_private; - - tegra->fbdev = tegra_fbdev_create(drm); - if (IS_ERR(tegra->fbdev)) - return PTR_ERR(tegra->fbdev); -#endif - - return 0; -} - -void tegra_drm_fb_free(struct drm_device *drm) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct tegra_drm *tegra = drm->dev_private; - - tegra_fbdev_free(tegra->fbdev); -#endif -} - -int tegra_drm_fb_init(struct drm_device *drm) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct tegra_drm *tegra = drm->dev_private; - int err; - - err = tegra_fbdev_init(tegra->fbdev, drm->mode_config.num_crtc, - drm->mode_config.num_connector); - if (err < 0) - return err; -#endif - - return 0; -} - -void tegra_drm_fb_exit(struct drm_device *drm) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct tegra_drm *tegra = drm->dev_private; - - tegra_fbdev_exit(tegra->fbdev); -#endif -} diff --git a/drivers/gpu/drm/tegra/fbdev.c b/drivers/gpu/drm/tegra/fbdev.c new file mode 100644 index 000000000000..dca9eccae466 --- /dev/null +++ b/drivers/gpu/drm/tegra/fbdev.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2012-2013 Avionic Design GmbH + * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. + * + * Based on the KMS/FB DMA helpers + * Copyright (C) 2012 Analog Devices Inc. + */ + +#include <linux/console.h> +#include <linux/vmalloc.h> + +#include <drm/drm_drv.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_modeset_helper.h> + +#include "drm.h" +#include "gem.h" + +static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct drm_fb_helper *helper = info->par; + struct tegra_bo *bo; + int err; + + bo = tegra_fb_get_plane(helper->fb, 0); + + err = drm_gem_mmap_obj(&bo->gem, bo->gem.size, vma); + if (err < 0) + return err; + + return __tegra_gem_mmap(&bo->gem, vma); +} + +static void tegra_fbdev_fb_destroy(struct fb_info *info) +{ + struct drm_fb_helper *helper = info->par; + struct drm_framebuffer *fb = helper->fb; + struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); + + drm_fb_helper_fini(helper); + + /* Undo the special mapping we made in fbdev probe. */ + if (bo->pages) { + vunmap(bo->vaddr); + bo->vaddr = NULL; + } + drm_framebuffer_remove(fb); + + drm_client_release(&helper->client); + drm_fb_helper_unprepare(helper); + kfree(helper); +} + +static const struct fb_ops tegra_fb_ops = { + .owner = THIS_MODULE, + DRM_FB_HELPER_DEFAULT_OPS, + .fb_read = drm_fb_helper_sys_read, + .fb_write = drm_fb_helper_sys_write, + .fb_fillrect = drm_fb_helper_sys_fillrect, + .fb_copyarea = drm_fb_helper_sys_copyarea, + .fb_imageblit = drm_fb_helper_sys_imageblit, + .fb_mmap = tegra_fb_mmap, + .fb_destroy = tegra_fbdev_fb_destroy, +}; + +static int tegra_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct tegra_drm *tegra = helper->dev->dev_private; + struct drm_device *drm = helper->dev; + struct drm_mode_fb_cmd2 cmd = { 0 }; + unsigned int bytes_per_pixel; + struct drm_framebuffer *fb; + unsigned long offset; + struct fb_info *info; + struct tegra_bo *bo; + size_t size; + int err; + + bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); + + cmd.width = sizes->surface_width; + cmd.height = sizes->surface_height; + cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, + tegra->pitch_align); + + cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + size = cmd.pitches[0] * cmd.height; + + bo = tegra_bo_create(drm, size, 0); + if (IS_ERR(bo)) + return PTR_ERR(bo); + + info = drm_fb_helper_alloc_info(helper); + if (IS_ERR(info)) { + dev_err(drm->dev, "failed to allocate framebuffer info\n"); + drm_gem_object_put(&bo->gem); + return PTR_ERR(info); + } + + fb = tegra_fb_alloc(drm, &cmd, &bo, 1); + if (IS_ERR(fb)) { + err = PTR_ERR(fb); + dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", + err); + drm_gem_object_put(&bo->gem); + return PTR_ERR(fb); + } + + helper->fb = fb; + helper->info = info; + + info->fbops = &tegra_fb_ops; + + drm_fb_helper_fill_info(info, helper, sizes); + + offset = info->var.xoffset * bytes_per_pixel + + info->var.yoffset * fb->pitches[0]; + + if (bo->pages) { + bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); + if (!bo->vaddr) { + dev_err(drm->dev, "failed to vmap() framebuffer\n"); + err = -ENOMEM; + goto destroy; + } + } + + info->screen_base = (void __iomem *)bo->vaddr + offset; + info->screen_size = size; + info->fix.smem_start = (unsigned long)(bo->iova + offset); + info->fix.smem_len = size; + + return 0; + +destroy: + drm_framebuffer_remove(fb); + return err; +} + +static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = { + .fb_probe = tegra_fbdev_probe, +}; + +/* + * struct drm_client + */ + +static void tegra_fbdev_client_unregister(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + + if (fb_helper->info) { + drm_fb_helper_unregister_info(fb_helper); + } else { + drm_client_release(&fb_helper->client); + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); + } +} + +static int tegra_fbdev_client_restore(struct drm_client_dev *client) +{ + drm_fb_helper_lastclose(client->dev); + + return 0; +} + +static int tegra_fbdev_client_hotplug(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + struct drm_device *dev = client->dev; + int ret; + + if (dev->fb_helper) + return drm_fb_helper_hotplug_event(dev->fb_helper); + + ret = drm_fb_helper_init(dev, fb_helper); + if (ret) + goto err_drm_err; + + if (!drm_drv_uses_atomic_modeset(dev)) + drm_helper_disable_unused_functions(dev); + + ret = drm_fb_helper_initial_config(fb_helper); + if (ret) + goto err_drm_fb_helper_fini; + + return 0; + +err_drm_fb_helper_fini: + drm_fb_helper_fini(fb_helper); +err_drm_err: + drm_err(dev, "Failed to setup fbdev emulation (ret=%d)\n", ret); + return ret; +} + +static const struct drm_client_funcs tegra_fbdev_client_funcs = { + .owner = THIS_MODULE, + .unregister = tegra_fbdev_client_unregister, + .restore = tegra_fbdev_client_restore, + .hotplug = tegra_fbdev_client_hotplug, +}; + +void tegra_fbdev_setup(struct drm_device *dev) +{ + struct drm_fb_helper *helper; + int ret; + + drm_WARN(dev, !dev->registered, "Device has not been registered.\n"); + drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n"); + + helper = kzalloc(sizeof(*helper), GFP_KERNEL); + if (!helper) + return; + drm_fb_helper_prepare(dev, helper, 32, &tegra_fb_helper_funcs); + + ret = drm_client_init(dev, &helper->client, "fbdev", &tegra_fbdev_client_funcs); + if (ret) + goto err_drm_client_init; + + ret = tegra_fbdev_client_hotplug(&helper->client); + if (ret) + drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); + + drm_client_register(&helper->client); + + return; + +err_drm_client_init: + drm_fb_helper_unprepare(helper); + kfree(helper); +} diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index bce991a2ccc0..dea38892d6e6 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -13,6 +13,7 @@ #include <linux/dma-buf.h> #include <linux/iommu.h> #include <linux/module.h> +#include <linux/vmalloc.h> #include <drm/drm_drv.h> #include <drm/drm_prime.h> diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index e3bb4c99ed39..50f77fddda54 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c @@ -295,19 +295,11 @@ static int gr2d_probe(struct platform_device *pdev) return 0; } -static int gr2d_remove(struct platform_device *pdev) +static void gr2d_remove(struct platform_device *pdev) { struct gr2d *gr2d = platform_get_drvdata(pdev); - int err; - - err = host1x_client_unregister(&gr2d->client.base); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } - return 0; + host1x_client_unregister(&gr2d->client.base); } static int __maybe_unused gr2d_runtime_suspend(struct device *dev) @@ -403,5 +395,5 @@ struct platform_driver tegra_gr2d_driver = { .pm = &tegra_gr2d_pm, }, .probe = gr2d_probe, - .remove = gr2d_remove, + .remove_new = gr2d_remove, }; diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index a1fd3113ea96..c026c2c916c1 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -550,19 +550,11 @@ static int gr3d_probe(struct platform_device *pdev) return 0; } -static int gr3d_remove(struct platform_device *pdev) +static void gr3d_remove(struct platform_device *pdev) { struct gr3d *gr3d = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&gr3d->client.base); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } - - return 0; + host1x_client_unregister(&gr3d->client.base); } static int __maybe_unused gr3d_runtime_suspend(struct device *dev) @@ -638,5 +630,5 @@ struct platform_driver tegra_gr3d_driver = { .pm = &tegra_gr3d_pm, }, .probe = gr3d_probe, - .remove = gr3d_remove, + .remove_new = gr3d_remove, }; diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 40ec3e6cf204..6eac54ae1205 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -1874,21 +1874,13 @@ static int tegra_hdmi_probe(struct platform_device *pdev) return 0; } -static int tegra_hdmi_remove(struct platform_device *pdev) +static void tegra_hdmi_remove(struct platform_device *pdev) { struct tegra_hdmi *hdmi = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&hdmi->client); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } + host1x_client_unregister(&hdmi->client); tegra_output_remove(&hdmi->output); - - return 0; } struct platform_driver tegra_hdmi_driver = { @@ -1897,5 +1889,5 @@ struct platform_driver tegra_hdmi_driver = { .of_match_table = tegra_hdmi_of_match, }, .probe = tegra_hdmi_probe, - .remove = tegra_hdmi_remove, + .remove_new = tegra_hdmi_remove, }; diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index b872527a123c..916857361a91 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -1174,17 +1174,12 @@ unregister: return err; } -static int tegra_display_hub_remove(struct platform_device *pdev) +static void tegra_display_hub_remove(struct platform_device *pdev) { struct tegra_display_hub *hub = platform_get_drvdata(pdev); unsigned int i; - int err; - err = host1x_client_unregister(&hub->client); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - } + host1x_client_unregister(&hub->client); for (i = 0; i < hub->soc->num_wgrps; i++) { struct tegra_windowgroup *wgrp = &hub->wgrps[i]; @@ -1193,8 +1188,6 @@ static int tegra_display_hub_remove(struct platform_device *pdev) } pm_runtime_disable(&pdev->dev); - - return err; } static const struct tegra_display_hub_soc tegra186_display_hub = { @@ -1226,5 +1219,5 @@ struct platform_driver tegra_display_hub_driver = { .of_match_table = tegra_display_hub_of_match, }, .probe = tegra_display_hub_probe, - .remove = tegra_display_hub_remove, + .remove_new = tegra_display_hub_remove, }; diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c index 86c5818ac27b..ae78a81e5eef 100644 --- a/drivers/gpu/drm/tegra/nvdec.c +++ b/drivers/gpu/drm/tegra/nvdec.c @@ -547,21 +547,13 @@ exit_falcon: return err; } -static int nvdec_remove(struct platform_device *pdev) +static void nvdec_remove(struct platform_device *pdev) { struct nvdec *nvdec = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&nvdec->client.base); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } + host1x_client_unregister(&nvdec->client.base); falcon_exit(&nvdec->falcon); - - return 0; } static const struct dev_pm_ops nvdec_pm_ops = { @@ -577,7 +569,7 @@ struct platform_driver tegra_nvdec_driver = { .pm = &nvdec_pm_ops }, .probe = nvdec_probe, - .remove = nvdec_remove, + .remove_new = nvdec_remove, }; #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index a8925dcd7edd..dc2dcb5ca1c8 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -4,6 +4,9 @@ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. */ +#include <linux/i2c.h> +#include <linux/of.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index 10090116895f..ffe5f06b770d 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -777,21 +777,17 @@ int tegra_plane_interconnect_init(struct tegra_plane *plane) plane->icc_mem = devm_of_icc_get(dev, icc_name); err = PTR_ERR_OR_ZERO(plane->icc_mem); - if (err) { - dev_err_probe(dev, err, "failed to get %s interconnect\n", - icc_name); - return err; - } + if (err) + return dev_err_probe(dev, err, "failed to get %s interconnect\n", + icc_name); /* plane B on T20/30 has a dedicated memory client for a 6-tap vertical filter */ if (plane->index == 1 && dc->soc->has_win_b_vfilter_mem_client) { plane->icc_mem_vfilter = devm_of_icc_get(dev, "winb-vfilter"); err = PTR_ERR_OR_ZERO(plane->icc_mem_vfilter); - if (err) { - dev_err_probe(dev, err, "failed to get %s interconnect\n", - "winb-vfilter"); - return err; - } + if (err) + return dev_err_probe(dev, err, "failed to get %s interconnect\n", + "winb-vfilter"); } return 0; diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index ff8fce36d2aa..79566c9ea8ff 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -5,6 +5,7 @@ */ #include <linux/clk.h> +#include <linux/of.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge_connector.h> @@ -250,12 +251,12 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc) return 0; } -int tegra_dc_rgb_remove(struct tegra_dc *dc) +void tegra_dc_rgb_remove(struct tegra_dc *dc) { struct tegra_rgb *rgb; if (!dc->rgb) - return 0; + return; rgb = to_rgb(dc->rgb); clk_put(rgb->pll_d2_out0); @@ -263,8 +264,6 @@ int tegra_dc_rgb_remove(struct tegra_dc *dc) tegra_output_remove(dc->rgb); dc->rgb = NULL; - - return 0; } int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc) diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 34af6724914f..fbb63d755496 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -1153,7 +1153,7 @@ static int tegra_sor_compute_config(struct tegra_sor *sor, struct drm_dp_link *link) { const u64 f = 100000, link_rate = link->rate * 1000; - const u64 pclk = mode->clock * 1000; + const u64 pclk = (u64)mode->clock * 1000; u64 input, output, watermark, num; struct tegra_sor_params params; u32 num_syms_per_line; @@ -2959,11 +2959,9 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor) int err; sor->avdd_io_supply = devm_regulator_get(sor->dev, "avdd-io-hdmi-dp"); - if (IS_ERR(sor->avdd_io_supply)) { - dev_err(sor->dev, "cannot get AVDD I/O supply: %ld\n", - PTR_ERR(sor->avdd_io_supply)); - return PTR_ERR(sor->avdd_io_supply); - } + if (IS_ERR(sor->avdd_io_supply)) + return dev_err_probe(sor->dev, PTR_ERR(sor->avdd_io_supply), + "cannot get AVDD I/O supply\n"); err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply); if (err < 0) { @@ -2973,11 +2971,9 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor) } sor->vdd_pll_supply = devm_regulator_get(sor->dev, "vdd-hdmi-dp-pll"); - if (IS_ERR(sor->vdd_pll_supply)) { - dev_err(sor->dev, "cannot get VDD PLL supply: %ld\n", - PTR_ERR(sor->vdd_pll_supply)); - return PTR_ERR(sor->vdd_pll_supply); - } + if (IS_ERR(sor->vdd_pll_supply)) + return dev_err_probe(sor->dev, PTR_ERR(sor->vdd_pll_supply), + "cannot get VDD PLL supply\n"); err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply); if (err < 0) { @@ -2987,11 +2983,9 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor) } sor->hdmi_supply = devm_regulator_get(sor->dev, "hdmi"); - if (IS_ERR(sor->hdmi_supply)) { - dev_err(sor->dev, "cannot get HDMI supply: %ld\n", - PTR_ERR(sor->hdmi_supply)); - return PTR_ERR(sor->hdmi_supply); - } + if (IS_ERR(sor->hdmi_supply)) + return dev_err_probe(sor->dev, PTR_ERR(sor->hdmi_supply), + "cannot get HDMI supply\n"); err = tegra_sor_enable_regulator(sor, sor->hdmi_supply); if (err < 0) { @@ -3794,10 +3788,8 @@ static int tegra_sor_probe(struct platform_device *pdev) } err = platform_get_irq(pdev, 0); - if (err < 0) { - dev_err(&pdev->dev, "failed to get IRQ: %d\n", err); + if (err < 0) goto remove; - } sor->irq = err; @@ -3973,17 +3965,11 @@ put_aux: return err; } -static int tegra_sor_remove(struct platform_device *pdev) +static void tegra_sor_remove(struct platform_device *pdev) { struct tegra_sor *sor = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&sor->client); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } + host1x_client_unregister(&sor->client); pm_runtime_disable(&pdev->dev); @@ -3993,8 +3979,6 @@ static int tegra_sor_remove(struct platform_device *pdev) } tegra_output_remove(&sor->output); - - return 0; } static int __maybe_unused tegra_sor_suspend(struct device *dev) @@ -4054,5 +4038,5 @@ struct platform_driver tegra_sor_driver = { .pm = &tegra_sor_pm_ops, }, .probe = tegra_sor_probe, - .remove = tegra_sor_remove, + .remove_new = tegra_sor_remove, }; diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index 531a71c72061..da7a038dca20 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -537,21 +537,13 @@ exit_falcon: return err; } -static int vic_remove(struct platform_device *pdev) +static void vic_remove(struct platform_device *pdev) { struct vic *vic = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&vic->client.base); - if (err < 0) { - dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", - err); - return err; - } + host1x_client_unregister(&vic->client.base); falcon_exit(&vic->falcon); - - return 0; } static const struct dev_pm_ops vic_pm_ops = { @@ -566,7 +558,7 @@ struct platform_driver tegra_vic_driver = { .pm = &vic_pm_ops }, .probe = vic_probe, - .remove = vic_remove, + .remove_new = vic_remove, }; #if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig index 1861a8180d3f..e6c78ae2003a 100644 --- a/drivers/gpu/host1x/Kconfig +++ b/drivers/gpu/host1x/Kconfig @@ -5,7 +5,7 @@ config TEGRA_HOST1X_CONTEXT_BUS config TEGRA_HOST1X tristate "NVIDIA Tegra host1x driver" - depends on ARCH_TEGRA || (ARM && COMPILE_TEST) + depends on ARCH_TEGRA || COMPILE_TEST select DMA_SHARED_BUFFER select TEGRA_HOST1X_CONTEXT_BUS select IOMMU_IOVA diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index bc7271a00a94..4d16a3396c4a 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -803,7 +803,7 @@ EXPORT_SYMBOL(__host1x_client_register); * Removes a host1x client from its host1x controller instance. If a logical * device has already been initialized, it will be torn down. */ -int host1x_client_unregister(struct host1x_client *client) +void host1x_client_unregister(struct host1x_client *client) { struct host1x_client *c; struct host1x *host1x; @@ -815,7 +815,7 @@ int host1x_client_unregister(struct host1x_client *client) err = host1x_del_client(host1x, client); if (!err) { mutex_unlock(&devices_lock); - return 0; + return; } } @@ -832,8 +832,6 @@ int host1x_client_unregister(struct host1x_client *client) mutex_unlock(&clients_lock); host1x_bo_cache_destroy(&client->cache); - - return 0; } EXPORT_SYMBOL(host1x_client_unregister); diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c index 8beedcf080ab..9ad89d22c0ca 100644 --- a/drivers/gpu/host1x/context.c +++ b/drivers/gpu/host1x/context.c @@ -13,6 +13,11 @@ #include "context.h" #include "dev.h" +static void host1x_memory_context_release(struct device *dev) +{ + /* context device is freed in host1x_memory_context_list_free() */ +} + int host1x_memory_context_list_init(struct host1x *host1x) { struct host1x_memory_context_list *cdl = &host1x->context_list; @@ -51,38 +56,41 @@ int host1x_memory_context_list_init(struct host1x *host1x) dev_set_name(&ctx->dev, "host1x-ctx.%d", i); ctx->dev.bus = &host1x_context_device_bus_type; ctx->dev.parent = host1x->dev; + ctx->dev.release = host1x_memory_context_release; dma_set_max_seg_size(&ctx->dev, UINT_MAX); err = device_add(&ctx->dev); if (err) { dev_err(host1x->dev, "could not add context device %d: %d\n", i, err); - goto del_devices; + put_device(&ctx->dev); + goto unreg_devices; } err = of_dma_configure_id(&ctx->dev, node, true, &i); if (err) { dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n", i, err); - device_del(&ctx->dev); - goto del_devices; + device_unregister(&ctx->dev); + goto unreg_devices; } if (!tegra_dev_iommu_get_stream_id(&ctx->dev, &ctx->stream_id) || !device_iommu_mapped(&ctx->dev)) { dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i); - device_del(&ctx->dev); - goto del_devices; + device_unregister(&ctx->dev); + goto unreg_devices; } } return 0; -del_devices: +unreg_devices: while (i--) - device_del(&cdl->devs[i].dev); + device_unregister(&cdl->devs[i].dev); kfree(cdl->devs); + cdl->devs = NULL; cdl->len = 0; return err; @@ -93,7 +101,7 @@ void host1x_memory_context_list_free(struct host1x_memory_context_list *cdl) unsigned int i; for (i = 0; i < cdl->len; i++) - device_del(&cdl->devs[i].dev); + device_unregister(&cdl->devs[i].dev); kfree(cdl->devs); cdl->len = 0; diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c index 2efe12dde8bc..4dcec535ec21 100644 --- a/drivers/gpu/host1x/mipi.c +++ b/drivers/gpu/host1x/mipi.c @@ -501,7 +501,6 @@ static int tegra_mipi_probe(struct platform_device *pdev) { const struct of_device_id *match; struct tegra_mipi *mipi; - struct resource *res; int err; match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node); @@ -515,8 +514,7 @@ static int tegra_mipi_probe(struct platform_device *pdev) mipi->soc = match->data; mipi->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mipi->regs = devm_ioremap_resource(&pdev->dev, res); + mipi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(mipi->regs)) return PTR_ERR(mipi->regs); diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index 2d2007760eac..f63d14a57a1d 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -248,7 +248,13 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, if (value) *value = host1x_syncpt_load(sp); - if (wait_err == 0) + /* + * Don't rely on dma_fence_wait_timeout return value, + * since it returns zero both on timeout and if the + * wait completed with 0 jiffies left. + */ + host1x_hw_syncpt_load(sp->host, sp); + if (wait_err == 0 && !host1x_syncpt_is_expired(sp, thresh)) return -EAGAIN; else if (wait_err < 0) return wait_err; diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 426e653bd55d..36ca639622c9 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -778,14 +778,8 @@ rpm_disable: static int tegra_csi_remove(struct platform_device *pdev) { struct tegra_csi *csi = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&csi->client); - if (err < 0) { - dev_err(&pdev->dev, - "failed to unregister host1x client: %d\n", err); - return err; - } + host1x_client_unregister(&csi->client); pm_runtime_disable(&pdev->dev); diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 11dd142c98c5..26f7aedce718 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -2041,14 +2041,8 @@ rpm_disable: static int tegra_vi_remove(struct platform_device *pdev) { struct tegra_vi *vi = platform_get_drvdata(pdev); - int err; - err = host1x_client_unregister(&vi->client); - if (err < 0) { - dev_err(&pdev->dev, - "failed to unregister host1x client: %d\n", err); - return err; - } + host1x_client_unregister(&vi->client); pm_runtime_disable(&pdev->dev); diff --git a/include/linux/host1x.h b/include/linux/host1x.h index 9a9de4b97a25..9c8119ed13a4 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -443,7 +443,7 @@ int __host1x_client_register(struct host1x_client *client); __host1x_client_register(client); \ }) -int host1x_client_unregister(struct host1x_client *client); +void host1x_client_unregister(struct host1x_client *client); int host1x_client_suspend(struct host1x_client *client); int host1x_client_resume(struct host1x_client *client); |