blob: c0b0f603af633027149f8f4574a8a858752270e5 [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +02002/*
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
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020010 */
11
Noralf Trønnes2de304b2019-01-14 13:10:59 +010012#include <drm/drm_fourcc.h>
Noralf Trønnes56286482017-08-13 15:31:45 +020013#include <drm/drm_framebuffer.h>
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020014#include <drm/drm_gem_cma_helper.h>
Noralf Trønnes56286482017-08-13 15:31:45 +020015#include <drm/drm_gem_framebuffer_helper.h>
Noralf Trønnes2de304b2019-01-14 13:10:59 +010016#include <drm/drm_plane.h>
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020017#include <linux/module.h>
18
Noralf Trønnes199c7712016-04-28 17:18:35 +020019/**
20 * DOC: framebuffer cma helper functions
21 *
22 * Provides helper functions for creating a cma (contiguous memory allocator)
23 * backed framebuffer.
24 *
Noralf Trønnesc0f095f2017-09-24 14:26:25 +020025 * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create
Noralf Trønnes02da16d2016-05-11 18:09:18 +020026 * callback function to create a cma backed framebuffer.
Noralf Trønnes199c7712016-04-28 17:18:35 +020027 */
28
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020029/**
30 * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer
31 * @fb: The framebuffer
32 * @plane: Which plane
33 *
34 * Return the CMA GEM object for given framebuffer.
35 *
36 * This function will usually be called from the CRTC callback functions.
37 */
38struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
Daniel Vetter890358a2016-05-31 23:11:12 +020039 unsigned int plane)
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020040{
Noralf Trønnes56286482017-08-13 15:31:45 +020041 struct drm_gem_object *gem;
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020042
Noralf Trønnes56286482017-08-13 15:31:45 +020043 gem = drm_gem_fb_get_obj(fb, plane);
44 if (!gem)
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020045 return NULL;
46
Noralf Trønnes56286482017-08-13 15:31:45 +020047 return to_drm_gem_cma_obj(gem);
Lars-Peter Clausen2e3b3c42012-07-02 16:37:47 +020048}
49EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
50
Marek Vasut14d7f962016-11-14 11:07:31 +010051/**
Alexandru Gheorghe042bf752018-11-01 17:02:05 +000052 * drm_fb_cma_get_gem_addr() - Get physical address for framebuffer, for pixel
53 * formats where values are grouped in blocks this will get you the beginning of
54 * the block
Yannick Fertre4636ce92017-04-14 12:13:32 +020055 * @fb: The framebuffer
56 * @state: Which state of drm plane
57 * @plane: Which plane
58 * Return the CMA GEM address for given framebuffer.
59 *
60 * This function will usually be called from the PLANE callback functions.
61 */
62dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
63 struct drm_plane_state *state,
64 unsigned int plane)
65{
Noralf Trønnes56286482017-08-13 15:31:45 +020066 struct drm_gem_cma_object *obj;
Yannick Fertre4636ce92017-04-14 12:13:32 +020067 dma_addr_t paddr;
Ayan Kumar Halderc76abab2018-08-17 17:54:00 +010068 u8 h_div = 1, v_div = 1;
Alexandru Gheorghe042bf752018-11-01 17:02:05 +000069 u32 block_w = drm_format_info_block_width(fb->format, plane);
70 u32 block_h = drm_format_info_block_height(fb->format, plane);
71 u32 block_size = fb->format->char_per_block[plane];
72 u32 sample_x;
73 u32 sample_y;
74 u32 block_start_y;
75 u32 num_hblocks;
Yannick Fertre4636ce92017-04-14 12:13:32 +020076
Noralf Trønnes56286482017-08-13 15:31:45 +020077 obj = drm_fb_cma_get_gem_obj(fb, plane);
78 if (!obj)
Yannick Fertre4636ce92017-04-14 12:13:32 +020079 return 0;
80
Noralf Trønnes56286482017-08-13 15:31:45 +020081 paddr = obj->paddr + fb->offsets[plane];
Ayan Kumar Halderc76abab2018-08-17 17:54:00 +010082
83 if (plane > 0) {
84 h_div = fb->format->hsub;
85 v_div = fb->format->vsub;
86 }
87
Alexandru Gheorghe042bf752018-11-01 17:02:05 +000088 sample_x = (state->src_x >> 16) / h_div;
89 sample_y = (state->src_y >> 16) / v_div;
90 block_start_y = (sample_y / block_h) * block_h;
91 num_hblocks = sample_x / block_w;
92
93 paddr += fb->pitches[plane] * block_start_y;
94 paddr += block_size * num_hblocks;
Yannick Fertre4636ce92017-04-14 12:13:32 +020095
96 return paddr;
97}
98EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);