root/drivers/gpu/drm/vboxvideo/vbox_fb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vboxfb_create
  2. vbox_fbdev_fini

   1 // SPDX-License-Identifier: MIT
   2 /*
   3  * Copyright (C) 2013-2017 Oracle Corporation
   4  * This file is based on ast_fb.c
   5  * Copyright 2012 Red Hat Inc.
   6  * Authors: Dave Airlie <airlied@redhat.com>
   7  *          Michael Thayer <michael.thayer@oracle.com,
   8  */
   9 #include <linux/delay.h>
  10 #include <linux/errno.h>
  11 #include <linux/fb.h>
  12 #include <linux/init.h>
  13 #include <linux/kernel.h>
  14 #include <linux/mm.h>
  15 #include <linux/module.h>
  16 #include <linux/pci.h>
  17 #include <linux/string.h>
  18 #include <linux/sysrq.h>
  19 #include <linux/tty.h>
  20 
  21 #include <drm/drm_crtc.h>
  22 #include <drm/drm_crtc_helper.h>
  23 #include <drm/drm_fb_helper.h>
  24 #include <drm/drm_fourcc.h>
  25 
  26 #include "vbox_drv.h"
  27 #include "vboxvideo.h"
  28 
  29 #ifdef CONFIG_DRM_KMS_FB_HELPER
  30 static struct fb_deferred_io vbox_defio = {
  31         .delay = HZ / 30,
  32         .deferred_io = drm_fb_helper_deferred_io,
  33 };
  34 #endif
  35 
  36 static struct fb_ops vboxfb_ops = {
  37         .owner = THIS_MODULE,
  38         DRM_FB_HELPER_DEFAULT_OPS,
  39         .fb_fillrect = drm_fb_helper_sys_fillrect,
  40         .fb_copyarea = drm_fb_helper_sys_copyarea,
  41         .fb_imageblit = drm_fb_helper_sys_imageblit,
  42 };
  43 
  44 int vboxfb_create(struct drm_fb_helper *helper,
  45                   struct drm_fb_helper_surface_size *sizes)
  46 {
  47         struct vbox_private *vbox =
  48                 container_of(helper, struct vbox_private, fb_helper);
  49         struct pci_dev *pdev = vbox->ddev.pdev;
  50         struct drm_mode_fb_cmd2 mode_cmd;
  51         struct drm_framebuffer *fb;
  52         struct fb_info *info;
  53         struct drm_gem_object *gobj;
  54         struct drm_gem_vram_object *gbo;
  55         int size, ret;
  56         s64 gpu_addr;
  57         u32 pitch;
  58 
  59         mode_cmd.width = sizes->surface_width;
  60         mode_cmd.height = sizes->surface_height;
  61         pitch = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
  62         mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
  63                                                           sizes->surface_depth);
  64         mode_cmd.pitches[0] = pitch;
  65 
  66         size = pitch * mode_cmd.height;
  67 
  68         ret = vbox_gem_create(vbox, size, true, &gobj);
  69         if (ret) {
  70                 DRM_ERROR("failed to create fbcon backing object %d\n", ret);
  71                 return ret;
  72         }
  73 
  74         ret = vbox_framebuffer_init(vbox, &vbox->afb, &mode_cmd, gobj);
  75         if (ret)
  76                 return ret;
  77 
  78         gbo = drm_gem_vram_of_gem(gobj);
  79 
  80         ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
  81         if (ret)
  82                 return ret;
  83 
  84         info = drm_fb_helper_alloc_fbi(helper);
  85         if (IS_ERR(info))
  86                 return PTR_ERR(info);
  87 
  88         info->screen_size = size;
  89         info->screen_base = (char __iomem *)drm_gem_vram_kmap(gbo, true, NULL);
  90         if (IS_ERR(info->screen_base))
  91                 return PTR_ERR(info->screen_base);
  92 
  93         fb = &vbox->afb.base;
  94         helper->fb = fb;
  95 
  96         info->fbops = &vboxfb_ops;
  97 
  98         /*
  99          * This seems to be done for safety checking that the framebuffer
 100          * is not registered twice by different drivers.
 101          */
 102         info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
 103         info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
 104 
 105         drm_fb_helper_fill_info(info, helper, sizes);
 106 
 107         gpu_addr = drm_gem_vram_offset(gbo);
 108         if (gpu_addr < 0)
 109                 return (int)gpu_addr;
 110         info->fix.smem_start = info->apertures->ranges[0].base + gpu_addr;
 111         info->fix.smem_len = vbox->available_vram_size - gpu_addr;
 112 
 113 #ifdef CONFIG_DRM_KMS_FB_HELPER
 114         info->fbdefio = &vbox_defio;
 115         fb_deferred_io_init(info);
 116 #endif
 117 
 118         info->pixmap.flags = FB_PIXMAP_SYSTEM;
 119 
 120         DRM_DEBUG_KMS("allocated %dx%d\n", fb->width, fb->height);
 121 
 122         return 0;
 123 }
 124 
 125 void vbox_fbdev_fini(struct vbox_private *vbox)
 126 {
 127         struct vbox_framebuffer *afb = &vbox->afb;
 128 
 129 #ifdef CONFIG_DRM_KMS_FB_HELPER
 130         if (vbox->fb_helper.fbdev && vbox->fb_helper.fbdev->fbdefio)
 131                 fb_deferred_io_cleanup(vbox->fb_helper.fbdev);
 132 #endif
 133 
 134         drm_fb_helper_unregister_fbi(&vbox->fb_helper);
 135 
 136         if (afb->obj) {
 137                 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(afb->obj);
 138 
 139                 drm_gem_vram_kunmap(gbo);
 140                 drm_gem_vram_unpin(gbo);
 141 
 142                 drm_gem_object_put_unlocked(afb->obj);
 143                 afb->obj = NULL;
 144         }
 145         drm_fb_helper_fini(&vbox->fb_helper);
 146 
 147         drm_framebuffer_unregister_private(&afb->base);
 148         drm_framebuffer_cleanup(&afb->base);
 149 }

/* [<][>][^][v][top][bottom][index][help] */