Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/tegra: Hide fbdev support behind config option

Only build tegra's fbdev emulation if CONFIG_DRM_FBDEV_EMULATION
has been enabled. As part of this change, move the code into its
own source file. No functional changes.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Thomas Zimmermann and committed by
Thierry Reding
1ac45068 43443460

+253 -225
+2
drivers/gpu/drm/tegra/Makefile
··· 29 29 30 30 tegra-drm-y += trace.o 31 31 32 + tegra-drm-$(CONFIG_DRM_FBDEV_EMULATION) += fbdev.o 33 + 32 34 obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
+20
drivers/gpu/drm/tegra/drm.h
··· 185 185 bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); 186 186 int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, 187 187 struct tegra_bo_tiling *tiling); 188 + struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm, 189 + const struct drm_mode_fb_cmd2 *mode_cmd, 190 + struct tegra_bo **planes, 191 + unsigned int num_planes); 188 192 struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, 189 193 struct drm_file *file, 190 194 const struct drm_mode_fb_cmd2 *cmd); 195 + 196 + #ifdef CONFIG_DRM_FBDEV_EMULATION 191 197 int tegra_drm_fb_prepare(struct drm_device *drm); 192 198 void tegra_drm_fb_free(struct drm_device *drm); 193 199 int tegra_drm_fb_init(struct drm_device *drm); 194 200 void tegra_drm_fb_exit(struct drm_device *drm); 201 + #else 202 + static inline int tegra_drm_fb_prepare(struct drm_device *drm) 203 + { 204 + return 0; 205 + } 206 + static inline void tegra_drm_fb_free(struct drm_device *drm) 207 + { } 208 + static inline int tegra_drm_fb_init(struct drm_device *drm) 209 + { 210 + return 0; 211 + } 212 + static inline void tegra_drm_fb_exit(struct drm_device *drm) 213 + { } 214 + #endif 195 215 196 216 extern struct platform_driver tegra_display_hub_driver; 197 217 extern struct platform_driver tegra_dc_driver;
+4 -225
drivers/gpu/drm/tegra/fb.c
··· 8 8 */ 9 9 10 10 #include <linux/console.h> 11 - #include <linux/vmalloc.h> 12 11 13 12 #include <drm/drm_fourcc.h> 14 13 #include <drm/drm_framebuffer.h> ··· 101 102 .create_handle = drm_gem_fb_create_handle, 102 103 }; 103 104 104 - static struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm, 105 - const struct drm_mode_fb_cmd2 *mode_cmd, 106 - struct tegra_bo **planes, 107 - unsigned int num_planes) 105 + struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm, 106 + const struct drm_mode_fb_cmd2 *mode_cmd, 107 + struct tegra_bo **planes, 108 + unsigned int num_planes) 108 109 { 109 110 struct drm_framebuffer *fb; 110 111 unsigned int i; ··· 178 179 drm_gem_object_put(&planes[i]->gem); 179 180 180 181 return ERR_PTR(err); 181 - } 182 - 183 - #ifdef CONFIG_DRM_FBDEV_EMULATION 184 - static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) 185 - { 186 - struct drm_fb_helper *helper = info->par; 187 - struct tegra_bo *bo; 188 - int err; 189 - 190 - bo = tegra_fb_get_plane(helper->fb, 0); 191 - 192 - err = drm_gem_mmap_obj(&bo->gem, bo->gem.size, vma); 193 - if (err < 0) 194 - return err; 195 - 196 - return __tegra_gem_mmap(&bo->gem, vma); 197 - } 198 - 199 - static const struct fb_ops tegra_fb_ops = { 200 - .owner = THIS_MODULE, 201 - DRM_FB_HELPER_DEFAULT_OPS, 202 - .fb_read = drm_fb_helper_sys_read, 203 - .fb_write = drm_fb_helper_sys_write, 204 - .fb_fillrect = drm_fb_helper_sys_fillrect, 205 - .fb_copyarea = drm_fb_helper_sys_copyarea, 206 - .fb_imageblit = drm_fb_helper_sys_imageblit, 207 - .fb_mmap = tegra_fb_mmap, 208 - }; 209 - 210 - static int tegra_fbdev_probe(struct drm_fb_helper *helper, 211 - struct drm_fb_helper_surface_size *sizes) 212 - { 213 - struct tegra_drm *tegra = helper->dev->dev_private; 214 - struct drm_device *drm = helper->dev; 215 - struct drm_mode_fb_cmd2 cmd = { 0 }; 216 - unsigned int bytes_per_pixel; 217 - struct drm_framebuffer *fb; 218 - unsigned long offset; 219 - struct fb_info *info; 220 - struct tegra_bo *bo; 221 - size_t size; 222 - int err; 223 - 224 - bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); 225 - 226 - cmd.width = sizes->surface_width; 227 - cmd.height = sizes->surface_height; 228 - cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, 229 - tegra->pitch_align); 230 - 231 - cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 232 - sizes->surface_depth); 233 - 234 - size = cmd.pitches[0] * cmd.height; 235 - 236 - bo = tegra_bo_create(drm, size, 0); 237 - if (IS_ERR(bo)) 238 - return PTR_ERR(bo); 239 - 240 - info = drm_fb_helper_alloc_info(helper); 241 - if (IS_ERR(info)) { 242 - dev_err(drm->dev, "failed to allocate framebuffer info\n"); 243 - drm_gem_object_put(&bo->gem); 244 - return PTR_ERR(info); 245 - } 246 - 247 - fb = tegra_fb_alloc(drm, &cmd, &bo, 1); 248 - if (IS_ERR(fb)) { 249 - err = PTR_ERR(fb); 250 - dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", 251 - err); 252 - drm_gem_object_put(&bo->gem); 253 - return PTR_ERR(fb); 254 - } 255 - 256 - helper->fb = fb; 257 - helper->info = info; 258 - 259 - info->fbops = &tegra_fb_ops; 260 - 261 - drm_fb_helper_fill_info(info, helper, sizes); 262 - 263 - offset = info->var.xoffset * bytes_per_pixel + 264 - info->var.yoffset * fb->pitches[0]; 265 - 266 - if (bo->pages) { 267 - bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP, 268 - pgprot_writecombine(PAGE_KERNEL)); 269 - if (!bo->vaddr) { 270 - dev_err(drm->dev, "failed to vmap() framebuffer\n"); 271 - err = -ENOMEM; 272 - goto destroy; 273 - } 274 - } 275 - 276 - info->screen_base = (void __iomem *)bo->vaddr + offset; 277 - info->screen_size = size; 278 - info->fix.smem_start = (unsigned long)(bo->iova + offset); 279 - info->fix.smem_len = size; 280 - 281 - return 0; 282 - 283 - destroy: 284 - drm_framebuffer_remove(fb); 285 - return err; 286 - } 287 - 288 - static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = { 289 - .fb_probe = tegra_fbdev_probe, 290 - }; 291 - 292 - static struct drm_fb_helper *tegra_fbdev_create(struct drm_device *drm) 293 - { 294 - struct drm_fb_helper *helper; 295 - 296 - helper = kzalloc(sizeof(*helper), GFP_KERNEL); 297 - if (!helper) { 298 - dev_err(drm->dev, "failed to allocate DRM fbdev\n"); 299 - return ERR_PTR(-ENOMEM); 300 - } 301 - 302 - drm_fb_helper_prepare(drm, helper, 32, &tegra_fb_helper_funcs); 303 - 304 - return helper; 305 - } 306 - 307 - static void tegra_fbdev_free(struct drm_fb_helper *helper) 308 - { 309 - drm_fb_helper_unprepare(helper); 310 - kfree(helper); 311 - } 312 - 313 - static int tegra_fbdev_init(struct drm_fb_helper *helper, 314 - unsigned int num_crtc, 315 - unsigned int max_connectors) 316 - { 317 - struct drm_device *drm = helper->dev; 318 - int err; 319 - 320 - err = drm_fb_helper_init(drm, helper); 321 - if (err < 0) { 322 - dev_err(drm->dev, "failed to initialize DRM FB helper: %d\n", 323 - err); 324 - return err; 325 - } 326 - 327 - err = drm_fb_helper_initial_config(helper); 328 - if (err < 0) { 329 - dev_err(drm->dev, "failed to set initial configuration: %d\n", 330 - err); 331 - goto fini; 332 - } 333 - 334 - return 0; 335 - 336 - fini: 337 - drm_fb_helper_fini(helper); 338 - return err; 339 - } 340 - 341 - static void tegra_fbdev_exit(struct drm_fb_helper *helper) 342 - { 343 - struct drm_framebuffer *fb = helper->fb; 344 - 345 - drm_fb_helper_unregister_info(helper); 346 - 347 - if (fb) { 348 - struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); 349 - 350 - /* Undo the special mapping we made in fbdev probe. */ 351 - if (bo && bo->pages) { 352 - vunmap(bo->vaddr); 353 - bo->vaddr = NULL; 354 - } 355 - 356 - drm_framebuffer_remove(fb); 357 - } 358 - 359 - drm_fb_helper_fini(helper); 360 - tegra_fbdev_free(helper); 361 - } 362 - #endif 363 - 364 - int tegra_drm_fb_prepare(struct drm_device *drm) 365 - { 366 - #ifdef CONFIG_DRM_FBDEV_EMULATION 367 - drm->fb_helper = tegra_fbdev_create(drm); 368 - if (IS_ERR(drm->fb_helper)) 369 - return PTR_ERR(drm->fb_helper); 370 - #endif 371 - 372 - return 0; 373 - } 374 - 375 - void tegra_drm_fb_free(struct drm_device *drm) 376 - { 377 - #ifdef CONFIG_DRM_FBDEV_EMULATION 378 - tegra_fbdev_free(drm->fb_helper); 379 - #endif 380 - } 381 - 382 - int tegra_drm_fb_init(struct drm_device *drm) 383 - { 384 - #ifdef CONFIG_DRM_FBDEV_EMULATION 385 - int err; 386 - 387 - err = tegra_fbdev_init(drm->fb_helper, drm->mode_config.num_crtc, 388 - drm->mode_config.num_connector); 389 - if (err < 0) 390 - return err; 391 - #endif 392 - 393 - return 0; 394 - } 395 - 396 - void tegra_drm_fb_exit(struct drm_device *drm) 397 - { 398 - #ifdef CONFIG_DRM_FBDEV_EMULATION 399 - tegra_fbdev_exit(drm->fb_helper); 400 - #endif 401 182 }
+227
drivers/gpu/drm/tegra/fbdev.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2012-2013 Avionic Design GmbH 4 + * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 5 + * 6 + * Based on the KMS/FB DMA helpers 7 + * Copyright (C) 2012 Analog Devices Inc. 8 + */ 9 + 10 + #include <linux/console.h> 11 + #include <linux/vmalloc.h> 12 + 13 + #include <drm/drm_fourcc.h> 14 + #include <drm/drm_framebuffer.h> 15 + #include <drm/drm_gem_framebuffer_helper.h> 16 + #include <drm/drm_modeset_helper.h> 17 + 18 + #include "drm.h" 19 + #include "gem.h" 20 + 21 + static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) 22 + { 23 + struct drm_fb_helper *helper = info->par; 24 + struct tegra_bo *bo; 25 + int err; 26 + 27 + bo = tegra_fb_get_plane(helper->fb, 0); 28 + 29 + err = drm_gem_mmap_obj(&bo->gem, bo->gem.size, vma); 30 + if (err < 0) 31 + return err; 32 + 33 + return __tegra_gem_mmap(&bo->gem, vma); 34 + } 35 + 36 + static const struct fb_ops tegra_fb_ops = { 37 + .owner = THIS_MODULE, 38 + DRM_FB_HELPER_DEFAULT_OPS, 39 + .fb_read = drm_fb_helper_sys_read, 40 + .fb_write = drm_fb_helper_sys_write, 41 + .fb_fillrect = drm_fb_helper_sys_fillrect, 42 + .fb_copyarea = drm_fb_helper_sys_copyarea, 43 + .fb_imageblit = drm_fb_helper_sys_imageblit, 44 + .fb_mmap = tegra_fb_mmap, 45 + }; 46 + 47 + static int tegra_fbdev_probe(struct drm_fb_helper *helper, 48 + struct drm_fb_helper_surface_size *sizes) 49 + { 50 + struct tegra_drm *tegra = helper->dev->dev_private; 51 + struct drm_device *drm = helper->dev; 52 + struct drm_mode_fb_cmd2 cmd = { 0 }; 53 + unsigned int bytes_per_pixel; 54 + struct drm_framebuffer *fb; 55 + unsigned long offset; 56 + struct fb_info *info; 57 + struct tegra_bo *bo; 58 + size_t size; 59 + int err; 60 + 61 + bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); 62 + 63 + cmd.width = sizes->surface_width; 64 + cmd.height = sizes->surface_height; 65 + cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, 66 + tegra->pitch_align); 67 + 68 + cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 69 + sizes->surface_depth); 70 + 71 + size = cmd.pitches[0] * cmd.height; 72 + 73 + bo = tegra_bo_create(drm, size, 0); 74 + if (IS_ERR(bo)) 75 + return PTR_ERR(bo); 76 + 77 + info = drm_fb_helper_alloc_info(helper); 78 + if (IS_ERR(info)) { 79 + dev_err(drm->dev, "failed to allocate framebuffer info\n"); 80 + drm_gem_object_put(&bo->gem); 81 + return PTR_ERR(info); 82 + } 83 + 84 + fb = tegra_fb_alloc(drm, &cmd, &bo, 1); 85 + if (IS_ERR(fb)) { 86 + err = PTR_ERR(fb); 87 + dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", 88 + err); 89 + drm_gem_object_put(&bo->gem); 90 + return PTR_ERR(fb); 91 + } 92 + 93 + helper->fb = fb; 94 + helper->info = info; 95 + 96 + info->fbops = &tegra_fb_ops; 97 + 98 + drm_fb_helper_fill_info(info, helper, sizes); 99 + 100 + offset = info->var.xoffset * bytes_per_pixel + 101 + info->var.yoffset * fb->pitches[0]; 102 + 103 + if (bo->pages) { 104 + bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP, 105 + pgprot_writecombine(PAGE_KERNEL)); 106 + if (!bo->vaddr) { 107 + dev_err(drm->dev, "failed to vmap() framebuffer\n"); 108 + err = -ENOMEM; 109 + goto destroy; 110 + } 111 + } 112 + 113 + info->screen_base = (void __iomem *)bo->vaddr + offset; 114 + info->screen_size = size; 115 + info->fix.smem_start = (unsigned long)(bo->iova + offset); 116 + info->fix.smem_len = size; 117 + 118 + return 0; 119 + 120 + destroy: 121 + drm_framebuffer_remove(fb); 122 + return err; 123 + } 124 + 125 + static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = { 126 + .fb_probe = tegra_fbdev_probe, 127 + }; 128 + 129 + static struct drm_fb_helper *tegra_fbdev_create(struct drm_device *drm) 130 + { 131 + struct drm_fb_helper *helper; 132 + 133 + helper = kzalloc(sizeof(*helper), GFP_KERNEL); 134 + if (!helper) 135 + return ERR_PTR(-ENOMEM); 136 + 137 + drm_fb_helper_prepare(drm, helper, 32, &tegra_fb_helper_funcs); 138 + 139 + return helper; 140 + } 141 + 142 + static void tegra_fbdev_free(struct drm_fb_helper *helper) 143 + { 144 + drm_fb_helper_unprepare(helper); 145 + kfree(helper); 146 + } 147 + 148 + static int tegra_fbdev_init(struct drm_fb_helper *helper, 149 + unsigned int num_crtc, 150 + unsigned int max_connectors) 151 + { 152 + struct drm_device *drm = helper->dev; 153 + int err; 154 + 155 + err = drm_fb_helper_init(drm, helper); 156 + if (err < 0) { 157 + dev_err(drm->dev, "failed to initialize DRM FB helper: %d\n", 158 + err); 159 + return err; 160 + } 161 + 162 + err = drm_fb_helper_initial_config(helper); 163 + if (err < 0) { 164 + dev_err(drm->dev, "failed to set initial configuration: %d\n", 165 + err); 166 + goto fini; 167 + } 168 + 169 + return 0; 170 + 171 + fini: 172 + drm_fb_helper_fini(helper); 173 + return err; 174 + } 175 + 176 + static void tegra_fbdev_exit(struct drm_fb_helper *helper) 177 + { 178 + struct drm_framebuffer *fb = helper->fb; 179 + 180 + drm_fb_helper_unregister_info(helper); 181 + 182 + if (fb) { 183 + struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); 184 + 185 + /* Undo the special mapping we made in fbdev probe. */ 186 + if (bo && bo->pages) { 187 + vunmap(bo->vaddr); 188 + bo->vaddr = NULL; 189 + } 190 + 191 + drm_framebuffer_remove(fb); 192 + } 193 + 194 + drm_fb_helper_fini(helper); 195 + tegra_fbdev_free(helper); 196 + } 197 + 198 + int tegra_drm_fb_prepare(struct drm_device *drm) 199 + { 200 + drm->fb_helper = tegra_fbdev_create(drm); 201 + if (IS_ERR(drm->fb_helper)) 202 + return PTR_ERR(drm->fb_helper); 203 + 204 + return 0; 205 + } 206 + 207 + void tegra_drm_fb_free(struct drm_device *drm) 208 + { 209 + tegra_fbdev_free(drm->fb_helper); 210 + } 211 + 212 + int tegra_drm_fb_init(struct drm_device *drm) 213 + { 214 + int err; 215 + 216 + err = tegra_fbdev_init(drm->fb_helper, drm->mode_config.num_crtc, 217 + drm->mode_config.num_connector); 218 + if (err < 0) 219 + return err; 220 + 221 + return 0; 222 + } 223 + 224 + void tegra_drm_fb_exit(struct drm_device *drm) 225 + { 226 + tegra_fbdev_exit(drm->fb_helper); 227 + }