From bca6272f79877458413f316b63d829e82bb4cbc5 Mon Sep 17 00:00:00 2001 From: Wookey Date: Fri, 16 Feb 2018 01:58:08 +0000 Subject: Use upstream source layout --- .../kernel/drivers/gpu/drm/pl111/pl111_drm_fb.c | 202 +++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100755 driver/product/kernel/drivers/gpu/drm/pl111/pl111_drm_fb.c (limited to 'driver/product/kernel/drivers/gpu/drm/pl111/pl111_drm_fb.c') diff --git a/driver/product/kernel/drivers/gpu/drm/pl111/pl111_drm_fb.c b/driver/product/kernel/drivers/gpu/drm/pl111/pl111_drm_fb.c new file mode 100755 index 0000000..f575c9e --- /dev/null +++ b/driver/product/kernel/drivers/gpu/drm/pl111/pl111_drm_fb.c @@ -0,0 +1,202 @@ +/* + * + * (C) COPYRIGHT 2012-2014 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + +/** + * pl111_drm_fb.c + * Implementation of the framebuffer functions for PL111 DRM + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "pl111_drm.h" + +static void pl111_fb_destroy(struct drm_framebuffer *framebuffer) +{ + struct pl111_drm_framebuffer *pl111_fb; +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + struct drm_crtc *crtc; + unsigned long flags; +#endif + DRM_DEBUG_KMS("Destroying framebuffer 0x%p...\n", framebuffer); + + pl111_fb = PL111_FB_FROM_FRAMEBUFFER(framebuffer); + + /* + * Because flips are deferred, wait for all previous flips to complete + */ + wait_event(priv.wait_for_flips, + atomic_read(&priv.nr_flips_in_flight) == 0); +#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS + /* + * Release KDS resources if it's currently being displayed. Only occurs + * when the last framebuffer is destroyed. + */ + list_for_each_entry(crtc, &framebuffer->dev->mode_config.crtc_list, + head) { + struct pl111_drm_crtc *pl111_crtc = to_pl111_crtc(crtc); + spin_lock_irqsave(&pl111_crtc->current_displaying_lock, flags); + if (pl111_crtc->displaying_fb == framebuffer) { + /* Release the current buffers */ + if (pl111_crtc->old_kds_res_set != NULL) { + DRM_DEBUG_KMS("Releasing KDS resources for "); + DRM_DEBUG_KMS("displayed 0x%p\n", framebuffer); + kds_resource_set_release( + &pl111_crtc->old_kds_res_set); + } + pl111_crtc->old_kds_res_set = NULL; + } + spin_unlock_irqrestore(&pl111_crtc->current_displaying_lock, + flags); + } +#endif + drm_framebuffer_cleanup(framebuffer); + + if ((pl111_fb->bo != NULL) && (&pl111_fb->bo->gem_object != NULL)) + drm_gem_object_unreference_unlocked(&pl111_fb->bo->gem_object); + + kfree(pl111_fb); + + DRM_DEBUG_KMS("Destroyed framebuffer 0x%p\n", framebuffer); +} + +static int pl111_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct pl111_gem_bo *bo = PL111_BO_FROM_FRAMEBUFFER(fb); + DRM_DEBUG_KMS("DRM %s on fb=%p\n", __func__, fb); + + if (bo == NULL) + return -EINVAL; + + return drm_gem_handle_create(file_priv, &bo->gem_object, handle); +} + +const struct drm_framebuffer_funcs fb_funcs = { + .destroy = pl111_fb_destroy, + .create_handle = pl111_fb_create_handle, +}; + +struct drm_framebuffer *pl111_fb_create(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct pl111_drm_framebuffer *pl111_fb = NULL; + struct drm_framebuffer *fb = NULL; + struct drm_gem_object *gem_obj; + struct pl111_gem_bo *bo; + int err = 0; + size_t min_size; + int bpp; + int depth; + + pr_info("DRM %s\n", __func__); + gem_obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (gem_obj == NULL) { + DRM_ERROR("Could not get gem obj from handle to create fb\n"); + err = -ENOENT; + goto error; + } + + bo = PL111_BO_FROM_GEM(gem_obj); + drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + if (mode_cmd->pitches[0] < mode_cmd->width * (bpp >> 3)) { + DRM_ERROR("bad pitch %u for plane 0\n", mode_cmd->pitches[0]); + err = -EINVAL; + goto error; + } + + min_size = (mode_cmd->height - 1) * mode_cmd->pitches[0] + + mode_cmd->width * (bpp >> 3); + + if (bo->gem_object.size < min_size) { + DRM_ERROR("gem obj size < min size\n"); + err = -EINVAL; + goto error; + } + + /* We can't scan out SHM so we can't create an fb for it */ + if (!(bo->type & PL111_BOT_DMA)) { + DRM_ERROR("Can't create FB for non-scanout buffer\n"); + err = -EINVAL; + goto error; + } + + switch ((char)(mode_cmd->pixel_format & 0xFF)) { + case 'Y': + case 'U': + case 'V': + case 'N': + case 'T': + DRM_ERROR("YUV formats not supported\n"); + err = -EINVAL; + goto error; + } + + pl111_fb = kzalloc(sizeof(struct pl111_drm_framebuffer), GFP_KERNEL); + if (pl111_fb == NULL) { + DRM_ERROR("Could not allocate pl111_drm_framebuffer\n"); + err = -ENOMEM; + goto error; + } + fb = &pl111_fb->fb; + + err = drm_framebuffer_init(dev, fb, &fb_funcs); + if (err) { + DRM_ERROR("drm_framebuffer_init failed\n"); + kfree(fb); + fb = NULL; + goto error; + } + + drm_helper_mode_fill_fb_struct(fb, mode_cmd); + + /* The only framebuffer formats supported by pl111 + * are 16 bpp or 32 bpp with 24 bit depth. + * See clcd_enable() + */ + if (!((fb->bits_per_pixel == 16) || + (fb->bits_per_pixel == 32 && fb->depth == 24))) { + DRM_DEBUG_KMS("unsupported pixel format bpp=%d, depth=%d\n", fb->bits_per_pixel, fb->depth); + drm_framebuffer_cleanup(fb); + kfree(fb); + fb = NULL; + err = -EINVAL; + goto error; + } + + pl111_fb->bo = bo; + + DRM_DEBUG_KMS("Created fb 0x%p with gem_obj 0x%p physaddr=0x%.8x\n", + fb, gem_obj, bo->backing_data.dma.fb_dev_addr); + + return fb; + +error: + if (gem_obj != NULL) + drm_gem_object_unreference_unlocked(gem_obj); + + return ERR_PTR(err); +} -- cgit v1.2.3