Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * drm kms/fb cma (contiguous memory allocator) helper functions
0004  *
0005  * Copyright (C) 2012 Analog Devices Inc.
0006  *   Author: Lars-Peter Clausen <lars@metafoo.de>
0007  *
0008  * Based on udl_fbdev.c
0009  *  Copyright (C) 2012 Red Hat
0010  */
0011 
0012 #include <drm/drm_damage_helper.h>
0013 #include <drm/drm_fb_cma_helper.h>
0014 #include <drm/drm_fourcc.h>
0015 #include <drm/drm_framebuffer.h>
0016 #include <drm/drm_gem_cma_helper.h>
0017 #include <drm/drm_gem_framebuffer_helper.h>
0018 #include <drm/drm_plane.h>
0019 #include <linux/dma-mapping.h>
0020 #include <linux/module.h>
0021 
0022 /**
0023  * DOC: framebuffer cma helper functions
0024  *
0025  * Provides helper functions for creating a cma (contiguous memory allocator)
0026  * backed framebuffer.
0027  *
0028  * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create
0029  * callback function to create a cma backed framebuffer.
0030  */
0031 
0032 /**
0033  * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer
0034  * @fb: The framebuffer
0035  * @plane: Which plane
0036  *
0037  * Return the CMA GEM object for given framebuffer.
0038  *
0039  * This function will usually be called from the CRTC callback functions.
0040  */
0041 struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
0042                           unsigned int plane)
0043 {
0044     struct drm_gem_object *gem;
0045 
0046     gem = drm_gem_fb_get_obj(fb, plane);
0047     if (!gem)
0048         return NULL;
0049 
0050     return to_drm_gem_cma_obj(gem);
0051 }
0052 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
0053 
0054 /**
0055  * drm_fb_cma_get_gem_addr() - Get physical address for framebuffer, for pixel
0056  * formats where values are grouped in blocks this will get you the beginning of
0057  * the block
0058  * @fb: The framebuffer
0059  * @state: Which state of drm plane
0060  * @plane: Which plane
0061  * Return the CMA GEM address for given framebuffer.
0062  *
0063  * This function will usually be called from the PLANE callback functions.
0064  */
0065 dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
0066                    struct drm_plane_state *state,
0067                    unsigned int plane)
0068 {
0069     struct drm_gem_cma_object *obj;
0070     dma_addr_t paddr;
0071     u8 h_div = 1, v_div = 1;
0072     u32 block_w = drm_format_info_block_width(fb->format, plane);
0073     u32 block_h = drm_format_info_block_height(fb->format, plane);
0074     u32 block_size = fb->format->char_per_block[plane];
0075     u32 sample_x;
0076     u32 sample_y;
0077     u32 block_start_y;
0078     u32 num_hblocks;
0079 
0080     obj = drm_fb_cma_get_gem_obj(fb, plane);
0081     if (!obj)
0082         return 0;
0083 
0084     paddr = obj->paddr + fb->offsets[plane];
0085 
0086     if (plane > 0) {
0087         h_div = fb->format->hsub;
0088         v_div = fb->format->vsub;
0089     }
0090 
0091     sample_x = (state->src_x >> 16) / h_div;
0092     sample_y = (state->src_y >> 16) / v_div;
0093     block_start_y = (sample_y / block_h) * block_h;
0094     num_hblocks = sample_x / block_w;
0095 
0096     paddr += fb->pitches[plane] * block_start_y;
0097     paddr += block_size * num_hblocks;
0098 
0099     return paddr;
0100 }
0101 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
0102 
0103 /**
0104  * drm_fb_cma_sync_non_coherent - Sync GEM object to non-coherent backing
0105  *  memory
0106  * @drm: DRM device
0107  * @old_state: Old plane state
0108  * @state: New plane state
0109  *
0110  * This function can be used by drivers that use damage clips and have
0111  * CMA GEM objects backed by non-coherent memory. Calling this function
0112  * in a plane's .atomic_update ensures that all the data in the backing
0113  * memory have been written to RAM.
0114  */
0115 void drm_fb_cma_sync_non_coherent(struct drm_device *drm,
0116                   struct drm_plane_state *old_state,
0117                   struct drm_plane_state *state)
0118 {
0119     const struct drm_format_info *finfo = state->fb->format;
0120     struct drm_atomic_helper_damage_iter iter;
0121     const struct drm_gem_cma_object *cma_obj;
0122     unsigned int offset, i;
0123     struct drm_rect clip;
0124     dma_addr_t daddr;
0125     size_t nb_bytes;
0126 
0127     for (i = 0; i < finfo->num_planes; i++) {
0128         cma_obj = drm_fb_cma_get_gem_obj(state->fb, i);
0129         if (!cma_obj->map_noncoherent)
0130             continue;
0131 
0132         daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
0133         drm_atomic_helper_damage_iter_init(&iter, old_state, state);
0134 
0135         drm_atomic_for_each_plane_damage(&iter, &clip) {
0136             /* Ignore x1/x2 values, invalidate complete lines */
0137             offset = clip.y1 * state->fb->pitches[i];
0138 
0139             nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i];
0140             dma_sync_single_for_device(drm->dev, daddr + offset,
0141                            nb_bytes, DMA_TO_DEVICE);
0142         }
0143     }
0144 }
0145 EXPORT_SYMBOL_GPL(drm_fb_cma_sync_non_coherent);