1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * drm kms/fb cma (contiguous memory allocator) helper functions 4 * 5 * Copyright (C) 2012 Analog Device Inc. 6 * Author: Lars-Peter Clausen <lars@metafoo.de> 7 * 8 * Based on udl_fbdev.c 9 * Copyright (C) 2012 Red Hat 10 */ 11 12#include <drm/drm_fb_cma_helper.h> 13#include <drm/drm_fourcc.h> 14#include <drm/drm_framebuffer.h> 15#include <drm/drm_gem_cma_helper.h> 16#include <drm/drm_gem_framebuffer_helper.h> 17#include <drm/drm_plane.h> 18#include <linux/module.h> 19 20/** 21 * DOC: framebuffer cma helper functions 22 * 23 * Provides helper functions for creating a cma (contiguous memory allocator) 24 * backed framebuffer. 25 * 26 * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create 27 * callback function to create a cma backed framebuffer. 28 */ 29 30/** 31 * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer 32 * @fb: The framebuffer 33 * @plane: Which plane 34 * 35 * Return the CMA GEM object for given framebuffer. 36 * 37 * This function will usually be called from the CRTC callback functions. 38 */ 39struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, 40 unsigned int plane) 41{ 42 struct drm_gem_object *gem; 43 44 gem = drm_gem_fb_get_obj(fb, plane); 45 if (!gem) 46 return NULL; 47 48 return to_drm_gem_cma_obj(gem); 49} 50EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); 51 52/** 53 * drm_fb_cma_get_gem_addr() - Get physical address for framebuffer, for pixel 54 * formats where values are grouped in blocks this will get you the beginning of 55 * the block 56 * @fb: The framebuffer 57 * @state: Which state of drm plane 58 * @plane: Which plane 59 * Return the CMA GEM address for given framebuffer. 60 * 61 * This function will usually be called from the PLANE callback functions. 62 */ 63dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb, 64 struct drm_plane_state *state, 65 unsigned int plane) 66{ 67 struct drm_gem_cma_object *obj; 68 dma_addr_t paddr; 69 u8 h_div = 1, v_div = 1; 70 u32 block_w = drm_format_info_block_width(fb->format, plane); 71 u32 block_h = drm_format_info_block_height(fb->format, plane); 72 u32 block_size = fb->format->char_per_block[plane]; 73 u32 sample_x; 74 u32 sample_y; 75 u32 block_start_y; 76 u32 num_hblocks; 77 78 obj = drm_fb_cma_get_gem_obj(fb, plane); 79 if (!obj) 80 return 0; 81 82 paddr = obj->paddr + fb->offsets[plane]; 83 84 if (plane > 0) { 85 h_div = fb->format->hsub; 86 v_div = fb->format->vsub; 87 } 88 89 sample_x = (state->src_x >> 16) / h_div; 90 sample_y = (state->src_y >> 16) / v_div; 91 block_start_y = (sample_y / block_h) * block_h; 92 num_hblocks = sample_x / block_w; 93 94 paddr += fb->pitches[plane] * block_start_y; 95 paddr += block_size * num_hblocks; 96 97 return paddr; 98} 99EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr); 100