[PATCH 2/7] drm/gma500: Move fbdev code into separate source file
Patrik Jakobsson
patrik.r.jakobsson at gmail.com
Mon Feb 27 07:48:10 UTC 2023
On Mon, Feb 27, 2023 at 8:41 AM Thomas Zimmermann <tzimmermann at suse.de> wrote:
>
> Hi
>
> Am 27.02.23 um 08:10 schrieb Patrik Jakobsson:
> > On Thu, Feb 23, 2023 at 1:17 PM Thomas Zimmermann <tzimmermann at suse.de> 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 at suse.de>
> >
> > 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
More information about the dri-devel
mailing list