On Mon, Feb 27, 2023 at 8:41 AM Thomas Zimmermann <tzimmermann@xxxxxxx> wrote: > > Hi > > Am 27.02.23 um 08:10 schrieb Patrik Jakobsson: > > On Thu, Feb 23, 2023 at 1:17 PM Thomas Zimmermann <tzimmermann@xxxxxxx> wrote: > >> > >> Move the fbdev emulation from framebuffer.c into fbdev.c. Only build > >> the source code if the Kconfig symbol has been selected. Remaining in > >> framebuffer.c is gma500's code for DRM frambuffers. No functional > >> hanges. > >> > >> Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> > > > > Hi Thomas, this patch doesn't apply to drm-misc. I seem to be missing > > drm_fb_helper_prepare/unprepare(). > > Could be. I'm on drm-tip for development. And we're in the merge window, > which is a bad time to sync-ing trees. Let me see if I can easiyl > backmerge now. Or otherwise things should stabilize after -rc1 has been > tagged. No worries, I'll just review this against drm-tip instead. > > Best regards > Thomas > > > > > -Patrik > > > >> --- > >> drivers/gpu/drm/gma500/Makefile | 1 + > >> drivers/gpu/drm/gma500/fbdev.c | 325 +++++++++++++++++++++++++++ > >> drivers/gpu/drm/gma500/framebuffer.c | 318 +------------------------- > >> drivers/gpu/drm/gma500/psb_drv.h | 17 ++ > >> 4 files changed, 346 insertions(+), 315 deletions(-) > >> create mode 100644 drivers/gpu/drm/gma500/fbdev.c > >> > >> diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile > >> index 63012bf2485a..4f302cd5e1a6 100644 > >> --- a/drivers/gpu/drm/gma500/Makefile > >> +++ b/drivers/gpu/drm/gma500/Makefile > >> @@ -38,5 +38,6 @@ gma500_gfx-y += \ > >> psb_irq.o > >> > >> gma500_gfx-$(CONFIG_ACPI) += opregion.o > >> +gma500_gfx-$(CONFIG_DRM_FBDEV_EMULATION) += fbdev.o > >> > >> obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o > >> diff --git a/drivers/gpu/drm/gma500/fbdev.c b/drivers/gpu/drm/gma500/fbdev.c > >> new file mode 100644 > >> index 000000000000..9ce76b11d256 > >> --- /dev/null > >> +++ b/drivers/gpu/drm/gma500/fbdev.c > >> @@ -0,0 +1,325 @@ > >> +// SPDX-License-Identifier: GPL-2.0-only > >> +/************************************************************************** > >> + * Copyright (c) 2007-2011, Intel Corporation. > >> + * All Rights Reserved. > >> + * > >> + **************************************************************************/ > >> + > >> +#include <linux/pfn_t.h> > >> + > >> +#include <drm/drm_crtc_helper.h> > >> +#include <drm/drm_fb_helper.h> > >> +#include <drm/drm_framebuffer.h> > >> + > >> +#include "gem.h" > >> +#include "psb_drv.h" > >> + > >> +/* > >> + * VM area struct > >> + */ > >> + > >> +static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf) > >> +{ > >> + struct vm_area_struct *vma = vmf->vma; > >> + struct drm_framebuffer *fb = vma->vm_private_data; > >> + struct drm_device *dev = fb->dev; > >> + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> + struct psb_gem_object *pobj = to_psb_gem_object(fb->obj[0]); > >> + int page_num; > >> + int i; > >> + unsigned long address; > >> + vm_fault_t ret = VM_FAULT_SIGBUS; > >> + unsigned long pfn; > >> + unsigned long phys_addr = (unsigned long)dev_priv->stolen_base + pobj->offset; > >> + > >> + page_num = vma_pages(vma); > >> + address = vmf->address - (vmf->pgoff << PAGE_SHIFT); > >> + > >> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > >> + > >> + for (i = 0; i < page_num; i++) { > >> + pfn = (phys_addr >> PAGE_SHIFT); > >> + > >> + ret = vmf_insert_mixed(vma, address, __pfn_to_pfn_t(pfn, PFN_DEV)); > >> + if (unlikely(ret & VM_FAULT_ERROR)) > >> + break; > >> + address += PAGE_SIZE; > >> + phys_addr += PAGE_SIZE; > >> + } > >> + return ret; > >> +} > >> + > >> +static void psbfb_vm_open(struct vm_area_struct *vma) > >> +{ } > >> + > >> +static void psbfb_vm_close(struct vm_area_struct *vma) > >> +{ } > >> + > >> +static const struct vm_operations_struct psbfb_vm_ops = { > >> + .fault = psbfb_vm_fault, > >> + .open = psbfb_vm_open, > >> + .close = psbfb_vm_close > >> +}; > >> + > >> +/* > >> + * struct fb_ops > >> + */ > >> + > >> +#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) > >> + > >> +static int psbfb_setcolreg(unsigned int regno, > >> + unsigned int red, unsigned int green, > >> + unsigned int blue, unsigned int transp, > >> + struct fb_info *info) > >> +{ > >> + struct drm_fb_helper *fb_helper = info->par; > >> + struct drm_framebuffer *fb = fb_helper->fb; > >> + uint32_t v; > >> + > >> + if (!fb) > >> + return -ENOMEM; > >> + > >> + if (regno > 255) > >> + return 1; > >> + > >> + red = CMAP_TOHW(red, info->var.red.length); > >> + blue = CMAP_TOHW(blue, info->var.blue.length); > >> + green = CMAP_TOHW(green, info->var.green.length); > >> + transp = CMAP_TOHW(transp, info->var.transp.length); > >> + > >> + v = (red << info->var.red.offset) | > >> + (green << info->var.green.offset) | > >> + (blue << info->var.blue.offset) | > >> + (transp << info->var.transp.offset); > >> + > >> + if (regno < 16) { > >> + switch (fb->format->cpp[0] * 8) { > >> + case 16: > >> + ((uint32_t *) info->pseudo_palette)[regno] = v; > >> + break; > >> + case 24: > >> + case 32: > >> + ((uint32_t *) info->pseudo_palette)[regno] = v; > >> + break; > >> + } > >> + } > >> + > >> + return 0; > >> +} > >> + > >> +static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) > >> +{ > >> + struct drm_fb_helper *fb_helper = info->par; > >> + struct drm_framebuffer *fb = fb_helper->fb; > >> + > >> + if (vma->vm_pgoff != 0) > >> + return -EINVAL; > >> + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) > >> + return -EINVAL; > >> + > >> + /* > >> + * If this is a GEM object then info->screen_base is the virtual > >> + * kernel remapping of the object. FIXME: Review if this is > >> + * suitable for our mmap work > >> + */ > >> + vma->vm_ops = &psbfb_vm_ops; > >> + vma->vm_private_data = (void *)fb; > >> + vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP; > >> + > >> + return 0; > >> +} > >> + > >> +static const struct fb_ops psbfb_unaccel_ops = { > >> + .owner = THIS_MODULE, > >> + DRM_FB_HELPER_DEFAULT_OPS, > >> + .fb_setcolreg = psbfb_setcolreg, > >> + .fb_read = drm_fb_helper_cfb_read, > >> + .fb_write = drm_fb_helper_cfb_write, > >> + .fb_fillrect = drm_fb_helper_cfb_fillrect, > >> + .fb_copyarea = drm_fb_helper_cfb_copyarea, > >> + .fb_imageblit = drm_fb_helper_cfb_imageblit, > >> + .fb_mmap = psbfb_mmap, > >> +}; > >> + > >> +/* > >> + * struct drm_fb_helper_funcs > >> + */ > >> + > >> +static int psbfb_create(struct drm_fb_helper *fb_helper, > >> + struct drm_fb_helper_surface_size *sizes) > >> +{ > >> + struct drm_device *dev = fb_helper->dev; > >> + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> + struct pci_dev *pdev = to_pci_dev(dev->dev); > >> + struct fb_info *info; > >> + struct drm_framebuffer *fb; > >> + struct drm_mode_fb_cmd2 mode_cmd; > >> + int size; > >> + int ret; > >> + struct psb_gem_object *backing; > >> + struct drm_gem_object *obj; > >> + u32 bpp, depth; > >> + > >> + mode_cmd.width = sizes->surface_width; > >> + mode_cmd.height = sizes->surface_height; > >> + bpp = sizes->surface_bpp; > >> + depth = sizes->surface_depth; > >> + > >> + /* No 24bit packed */ > >> + if (bpp == 24) > >> + bpp = 32; > >> + > >> + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * DIV_ROUND_UP(bpp, 8), 64); > >> + > >> + size = mode_cmd.pitches[0] * mode_cmd.height; > >> + size = ALIGN(size, PAGE_SIZE); > >> + > >> + /* Allocate the framebuffer in the GTT with stolen page backing */ > >> + backing = psb_gem_create(dev, size, "fb", true, PAGE_SIZE); > >> + if (IS_ERR(backing)) > >> + return PTR_ERR(backing); > >> + obj = &backing->base; > >> + > >> + memset(dev_priv->vram_addr + backing->offset, 0, size); > >> + > >> + info = drm_fb_helper_alloc_info(fb_helper); > >> + if (IS_ERR(info)) { > >> + ret = PTR_ERR(info); > >> + goto err_drm_gem_object_put; > >> + } > >> + > >> + mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); > >> + > >> + fb = psb_framebuffer_create(dev, &mode_cmd, obj); > >> + if (IS_ERR(fb)) { > >> + ret = PTR_ERR(fb); > >> + goto err_drm_gem_object_put; > >> + } > >> + > >> + fb_helper->fb = fb; > >> + > >> + info->fbops = &psbfb_unaccel_ops; > >> + > >> + info->fix.smem_start = dev_priv->fb_base; > >> + info->fix.smem_len = size; > >> + info->fix.ywrapstep = 0; > >> + info->fix.ypanstep = 0; > >> + > >> + /* Accessed stolen memory directly */ > >> + info->screen_base = dev_priv->vram_addr + backing->offset; > >> + info->screen_size = size; > >> + > >> + drm_fb_helper_fill_info(info, fb_helper, sizes); > >> + > >> + info->fix.mmio_start = pci_resource_start(pdev, 0); > >> + info->fix.mmio_len = pci_resource_len(pdev, 0); > >> + > >> + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ > >> + > >> + dev_dbg(dev->dev, "allocated %dx%d fb\n", fb->width, fb->height); > >> + > >> + return 0; > >> + > >> +err_drm_gem_object_put: > >> + drm_gem_object_put(obj); > >> + return ret; > >> +} > >> + > >> +static int psbfb_probe(struct drm_fb_helper *fb_helper, > >> + struct drm_fb_helper_surface_size *sizes) > >> +{ > >> + struct drm_device *dev = fb_helper->dev; > >> + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> + unsigned int fb_size; > >> + int bytespp; > >> + > >> + bytespp = sizes->surface_bpp / 8; > >> + if (bytespp == 3) /* no 24bit packed */ > >> + bytespp = 4; > >> + > >> + /* > >> + * If the mode will not fit in 32bit then switch to 16bit to get > >> + * a console on full resolution. The X mode setting server will > >> + * allocate its own 32bit GEM framebuffer > >> + */ > >> + fb_size = ALIGN(sizes->surface_width * bytespp, 64) * > >> + sizes->surface_height; > >> + fb_size = ALIGN(fb_size, PAGE_SIZE); > >> + > >> + if (fb_size > dev_priv->vram_stolen_size) { > >> + sizes->surface_bpp = 16; > >> + sizes->surface_depth = 16; > >> + } > >> + > >> + return psbfb_create(fb_helper, sizes); > >> +} > >> + > >> +static const struct drm_fb_helper_funcs psb_fb_helper_funcs = { > >> + .fb_probe = psbfb_probe, > >> +}; > >> + > >> +static int psb_fbdev_destroy(struct drm_device *dev, > >> + struct drm_fb_helper *fb_helper) > >> +{ > >> + struct drm_framebuffer *fb = fb_helper->fb; > >> + > >> + drm_fb_helper_unregister_info(fb_helper); > >> + > >> + drm_fb_helper_fini(fb_helper); > >> + drm_framebuffer_unregister_private(fb); > >> + drm_framebuffer_cleanup(fb); > >> + > >> + if (fb->obj[0]) > >> + drm_gem_object_put(fb->obj[0]); > >> + kfree(fb); > >> + > >> + return 0; > >> +} > >> + > >> +int psb_fbdev_init(struct drm_device *dev) > >> +{ > >> + struct drm_fb_helper *fb_helper; > >> + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> + int ret; > >> + > >> + fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); > >> + if (!fb_helper) > >> + return -ENOMEM; > >> + > >> + dev_priv->fb_helper = fb_helper; > >> + > >> + drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fb_helper_funcs); > >> + > >> + ret = drm_fb_helper_init(dev, fb_helper); > >> + if (ret) > >> + goto free; > >> + > >> + /* disable all the possible outputs/crtcs before entering KMS mode */ > >> + drm_helper_disable_unused_functions(dev); > >> + > >> + ret = drm_fb_helper_initial_config(fb_helper); > >> + if (ret) > >> + goto fini; > >> + > >> + return 0; > >> + > >> +fini: > >> + drm_fb_helper_fini(fb_helper); > >> +free: > >> + drm_fb_helper_unprepare(fb_helper); > >> + kfree(fb_helper); > >> + return ret; > >> +} > >> + > >> +void psb_fbdev_fini(struct drm_device *dev) > >> +{ > >> + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> + > >> + if (!dev_priv->fb_helper) > >> + return; > >> + > >> + psb_fbdev_destroy(dev, dev_priv->fb_helper); > >> + drm_fb_helper_unprepare(dev_priv->fb_helper); > >> + kfree(dev_priv->fb_helper); > >> + dev_priv->fb_helper = NULL; > >> +} > >> diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c > >> index df4dbc509f68..506b881a7b24 100644 > >> --- a/drivers/gpu/drm/gma500/framebuffer.c > >> +++ b/drivers/gpu/drm/gma500/framebuffer.c > >> @@ -5,16 +5,12 @@ > >> * > >> **************************************************************************/ > >> > >> -#include <linux/pfn_t.h> > >> - > >> -#include <drm/drm_crtc_helper.h> > >> #include <drm/drm_fb_helper.h> > >> #include <drm/drm_framebuffer.h> > >> #include <drm/drm_gem_framebuffer_helper.h> > >> #include <drm/drm_modeset_helper.h> > >> > >> #include "framebuffer.h" > >> -#include "gem.h" > >> #include "psb_drv.h" > >> > >> static const struct drm_framebuffer_funcs psb_fb_funcs = { > >> @@ -22,126 +18,6 @@ static const struct drm_framebuffer_funcs psb_fb_funcs = { > >> .create_handle = drm_gem_fb_create_handle, > >> }; > >> > >> -#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) > >> - > >> -static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green, > >> - unsigned blue, unsigned transp, > >> - struct fb_info *info) > >> -{ > >> - struct drm_fb_helper *fb_helper = info->par; > >> - struct drm_framebuffer *fb = fb_helper->fb; > >> - uint32_t v; > >> - > >> - if (!fb) > >> - return -ENOMEM; > >> - > >> - if (regno > 255) > >> - return 1; > >> - > >> - red = CMAP_TOHW(red, info->var.red.length); > >> - blue = CMAP_TOHW(blue, info->var.blue.length); > >> - green = CMAP_TOHW(green, info->var.green.length); > >> - transp = CMAP_TOHW(transp, info->var.transp.length); > >> - > >> - v = (red << info->var.red.offset) | > >> - (green << info->var.green.offset) | > >> - (blue << info->var.blue.offset) | > >> - (transp << info->var.transp.offset); > >> - > >> - if (regno < 16) { > >> - switch (fb->format->cpp[0] * 8) { > >> - case 16: > >> - ((uint32_t *) info->pseudo_palette)[regno] = v; > >> - break; > >> - case 24: > >> - case 32: > >> - ((uint32_t *) info->pseudo_palette)[regno] = v; > >> - break; > >> - } > >> - } > >> - > >> - return 0; > >> -} > >> - > >> -static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf) > >> -{ > >> - struct vm_area_struct *vma = vmf->vma; > >> - struct drm_framebuffer *fb = vma->vm_private_data; > >> - struct drm_device *dev = fb->dev; > >> - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> - struct psb_gem_object *pobj = to_psb_gem_object(fb->obj[0]); > >> - int page_num; > >> - int i; > >> - unsigned long address; > >> - vm_fault_t ret = VM_FAULT_SIGBUS; > >> - unsigned long pfn; > >> - unsigned long phys_addr = (unsigned long)dev_priv->stolen_base + pobj->offset; > >> - > >> - page_num = vma_pages(vma); > >> - address = vmf->address - (vmf->pgoff << PAGE_SHIFT); > >> - > >> - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > >> - > >> - for (i = 0; i < page_num; i++) { > >> - pfn = (phys_addr >> PAGE_SHIFT); > >> - > >> - ret = vmf_insert_mixed(vma, address, > >> - __pfn_to_pfn_t(pfn, PFN_DEV)); > >> - if (unlikely(ret & VM_FAULT_ERROR)) > >> - break; > >> - address += PAGE_SIZE; > >> - phys_addr += PAGE_SIZE; > >> - } > >> - return ret; > >> -} > >> - > >> -static void psbfb_vm_open(struct vm_area_struct *vma) > >> -{ > >> -} > >> - > >> -static void psbfb_vm_close(struct vm_area_struct *vma) > >> -{ > >> -} > >> - > >> -static const struct vm_operations_struct psbfb_vm_ops = { > >> - .fault = psbfb_vm_fault, > >> - .open = psbfb_vm_open, > >> - .close = psbfb_vm_close > >> -}; > >> - > >> -static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) > >> -{ > >> - struct drm_fb_helper *fb_helper = info->par; > >> - struct drm_framebuffer *fb = fb_helper->fb; > >> - > >> - if (vma->vm_pgoff != 0) > >> - return -EINVAL; > >> - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) > >> - return -EINVAL; > >> - > >> - /* > >> - * If this is a GEM object then info->screen_base is the virtual > >> - * kernel remapping of the object. FIXME: Review if this is > >> - * suitable for our mmap work > >> - */ > >> - vma->vm_ops = &psbfb_vm_ops; > >> - vma->vm_private_data = (void *)fb; > >> - vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP; > >> - return 0; > >> -} > >> - > >> -static const struct fb_ops psbfb_unaccel_ops = { > >> - .owner = THIS_MODULE, > >> - DRM_FB_HELPER_DEFAULT_OPS, > >> - .fb_setcolreg = psbfb_setcolreg, > >> - .fb_read = drm_fb_helper_cfb_read, > >> - .fb_write = drm_fb_helper_cfb_write, > >> - .fb_fillrect = drm_fb_helper_cfb_fillrect, > >> - .fb_copyarea = drm_fb_helper_cfb_copyarea, > >> - .fb_imageblit = drm_fb_helper_cfb_imageblit, > >> - .fb_mmap = psbfb_mmap, > >> -}; > >> - > >> /** > >> * psb_framebuffer_init - initialize a framebuffer > >> * @dev: our DRM device > >> @@ -192,11 +68,9 @@ static int psb_framebuffer_init(struct drm_device *dev, > >> * > >> * TODO: review object references > >> */ > >> - > >> -static struct drm_framebuffer *psb_framebuffer_create > >> - (struct drm_device *dev, > >> - const struct drm_mode_fb_cmd2 *mode_cmd, > >> - struct drm_gem_object *obj) > >> +struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev, > >> + const struct drm_mode_fb_cmd2 *mode_cmd, > >> + struct drm_gem_object *obj) > >> { > >> struct drm_framebuffer *fb; > >> int ret; > >> @@ -213,93 +87,6 @@ static struct drm_framebuffer *psb_framebuffer_create > >> return fb; > >> } > >> > >> -/** > >> - * psbfb_create - create a framebuffer > >> - * @fb_helper: the framebuffer helper > >> - * @sizes: specification of the layout > >> - * > >> - * Create a framebuffer to the specifications provided > >> - */ > >> -static int psbfb_create(struct drm_fb_helper *fb_helper, > >> - struct drm_fb_helper_surface_size *sizes) > >> -{ > >> - struct drm_device *dev = fb_helper->dev; > >> - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> - struct pci_dev *pdev = to_pci_dev(dev->dev); > >> - struct fb_info *info; > >> - struct drm_framebuffer *fb; > >> - struct drm_mode_fb_cmd2 mode_cmd; > >> - int size; > >> - int ret; > >> - struct psb_gem_object *backing; > >> - struct drm_gem_object *obj; > >> - u32 bpp, depth; > >> - > >> - mode_cmd.width = sizes->surface_width; > >> - mode_cmd.height = sizes->surface_height; > >> - bpp = sizes->surface_bpp; > >> - depth = sizes->surface_depth; > >> - > >> - /* No 24bit packed */ > >> - if (bpp == 24) > >> - bpp = 32; > >> - > >> - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * DIV_ROUND_UP(bpp, 8), 64); > >> - > >> - size = mode_cmd.pitches[0] * mode_cmd.height; > >> - size = ALIGN(size, PAGE_SIZE); > >> - > >> - /* Allocate the framebuffer in the GTT with stolen page backing */ > >> - backing = psb_gem_create(dev, size, "fb", true, PAGE_SIZE); > >> - if (IS_ERR(backing)) > >> - return PTR_ERR(backing); > >> - obj = &backing->base; > >> - > >> - memset(dev_priv->vram_addr + backing->offset, 0, size); > >> - > >> - info = drm_fb_helper_alloc_info(fb_helper); > >> - if (IS_ERR(info)) { > >> - ret = PTR_ERR(info); > >> - goto err_drm_gem_object_put; > >> - } > >> - > >> - mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); > >> - > >> - fb = psb_framebuffer_create(dev, &mode_cmd, obj); > >> - if (IS_ERR(fb)) { > >> - ret = PTR_ERR(fb); > >> - goto err_drm_gem_object_put; > >> - } > >> - > >> - fb_helper->fb = fb; > >> - > >> - info->fbops = &psbfb_unaccel_ops; > >> - > >> - info->fix.smem_start = dev_priv->fb_base; > >> - info->fix.smem_len = size; > >> - info->fix.ywrapstep = 0; > >> - info->fix.ypanstep = 0; > >> - > >> - /* Accessed stolen memory directly */ > >> - info->screen_base = dev_priv->vram_addr + backing->offset; > >> - info->screen_size = size; > >> - > >> - drm_fb_helper_fill_info(info, fb_helper, sizes); > >> - > >> - info->fix.mmio_start = pci_resource_start(pdev, 0); > >> - info->fix.mmio_len = pci_resource_len(pdev, 0); > >> - > >> - /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ > >> - > >> - dev_dbg(dev->dev, "allocated %dx%d fb\n", fb->width, fb->height); > >> - > >> - return 0; > >> - > >> -err_drm_gem_object_put: > >> - drm_gem_object_put(obj); > >> - return ret; > >> -} > >> - > >> /** > >> * psb_user_framebuffer_create - create framebuffer > >> * @dev: our DRM device > >> @@ -331,105 +118,6 @@ static struct drm_framebuffer *psb_user_framebuffer_create > >> return fb; > >> } > >> > >> -static int psbfb_probe(struct drm_fb_helper *fb_helper, > >> - struct drm_fb_helper_surface_size *sizes) > >> -{ > >> - struct drm_device *dev = fb_helper->dev; > >> - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> - unsigned int fb_size; > >> - int bytespp; > >> - > >> - bytespp = sizes->surface_bpp / 8; > >> - if (bytespp == 3) /* no 24bit packed */ > >> - bytespp = 4; > >> - > >> - /* If the mode will not fit in 32bit then switch to 16bit to get > >> - a console on full resolution. The X mode setting server will > >> - allocate its own 32bit GEM framebuffer */ > >> - fb_size = ALIGN(sizes->surface_width * bytespp, 64) * > >> - sizes->surface_height; > >> - fb_size = ALIGN(fb_size, PAGE_SIZE); > >> - > >> - if (fb_size > dev_priv->vram_stolen_size) { > >> - sizes->surface_bpp = 16; > >> - sizes->surface_depth = 16; > >> - } > >> - > >> - return psbfb_create(fb_helper, sizes); > >> -} > >> - > >> -static const struct drm_fb_helper_funcs psb_fb_helper_funcs = { > >> - .fb_probe = psbfb_probe, > >> -}; > >> - > >> -static int psb_fbdev_destroy(struct drm_device *dev, > >> - struct drm_fb_helper *fb_helper) > >> -{ > >> - struct drm_framebuffer *fb = fb_helper->fb; > >> - > >> - drm_fb_helper_unregister_info(fb_helper); > >> - > >> - drm_fb_helper_fini(fb_helper); > >> - drm_framebuffer_unregister_private(fb); > >> - drm_framebuffer_cleanup(fb); > >> - > >> - if (fb->obj[0]) > >> - drm_gem_object_put(fb->obj[0]); > >> - kfree(fb); > >> - > >> - return 0; > >> -} > >> - > >> -int psb_fbdev_init(struct drm_device *dev) > >> -{ > >> - struct drm_fb_helper *fb_helper; > >> - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> - int ret; > >> - > >> - fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); > >> - if (!fb_helper) { > >> - dev_err(dev->dev, "no memory\n"); > >> - return -ENOMEM; > >> - } > >> - > >> - dev_priv->fb_helper = fb_helper; > >> - > >> - drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fb_helper_funcs); > >> - > >> - ret = drm_fb_helper_init(dev, fb_helper); > >> - if (ret) > >> - goto free; > >> - > >> - /* disable all the possible outputs/crtcs before entering KMS mode */ > >> - drm_helper_disable_unused_functions(dev); > >> - > >> - ret = drm_fb_helper_initial_config(fb_helper); > >> - if (ret) > >> - goto fini; > >> - > >> - return 0; > >> - > >> -fini: > >> - drm_fb_helper_fini(fb_helper); > >> -free: > >> - drm_fb_helper_unprepare(fb_helper); > >> - kfree(fb_helper); > >> - return ret; > >> -} > >> - > >> -static void psb_fbdev_fini(struct drm_device *dev) > >> -{ > >> - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); > >> - > >> - if (!dev_priv->fb_helper) > >> - return; > >> - > >> - psb_fbdev_destroy(dev, dev_priv->fb_helper); > >> - drm_fb_helper_unprepare(dev_priv->fb_helper); > >> - kfree(dev_priv->fb_helper); > >> - dev_priv->fb_helper = NULL; > >> -} > >> - > >> static const struct drm_mode_config_funcs psb_mode_funcs = { > >> .fb_create = psb_user_framebuffer_create, > >> .output_poll_changed = drm_fb_helper_output_poll_changed, > >> diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h > >> index a5df6d2f2cab..cd0a30011572 100644 > >> --- a/drivers/gpu/drm/gma500/psb_drv.h > >> +++ b/drivers/gpu/drm/gma500/psb_drv.h > >> @@ -610,7 +610,24 @@ extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); > >> /* modesetting */ > >> extern void psb_modeset_init(struct drm_device *dev); > >> extern void psb_modeset_cleanup(struct drm_device *dev); > >> + > >> +/* framebuffer */ > >> +extern struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev, > >> + const struct drm_mode_fb_cmd2 *mode_cmd, > >> + struct drm_gem_object *obj); > >> + > >> +/* fbdev */ > >> +#if defined(CONFIG_DRM_FBDEV_EMULATION) > >> extern int psb_fbdev_init(struct drm_device *dev); > >> +extern void psb_fbdev_fini(struct drm_device *dev); > >> +#else > >> +int psb_fbdev_init(struct drm_device *dev) > >> +{ > >> + return 0; > >> +} > >> +void psb_fbdev_fini(struct drm_device *dev) > >> +{ } > >> +#endif > >> > >> /* backlight.c */ > >> int gma_backlight_init(struct drm_device *dev); > >> -- > >> 2.39.2 > >> > > -- > Thomas Zimmermann > Graphics Driver Developer > SUSE Software Solutions Germany GmbH > Maxfeldstr. 5, 90409 Nürnberg, Germany > (HRB 36809, AG Nürnberg) > Geschäftsführer: Ivo Totev