aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/arm
diff options
context:
space:
mode:
authorjames qian wang (Arm Technology China) <james.qian.wang@arm.com>2019-01-03 06:41:13 -0500
committerLiviu Dudau <Liviu.Dudau@arm.com>2019-01-14 06:20:11 -0500
commitc46c24bb6b115b0d74789cf089894384875189c7 (patch)
tree1ecef26b05cf1895eddd07ecdadaed385f0bc64f /drivers/gpu/drm/arm
parent981d29d2db7c96b942aa4b73fed31469140bcf9d (diff)
drm/komeda: Add komeda_framebuffer
komeda_framebuffer is for extending drm_framebuffer to add komeda own attributes and komeda specific fb handling. Changes in v3: - Fixed style problem found by checkpatch.pl --strict. Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com> Acked-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
Diffstat (limited to 'drivers/gpu/drm/arm')
-rw-r--r--drivers/gpu/drm/arm/display/komeda/Makefile3
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c165
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h34
3 files changed, 201 insertions, 1 deletions
diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index 394fc2aa434a..25beae900ed2 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -8,7 +8,8 @@ komeda-y := \
8 komeda_drv.o \ 8 komeda_drv.o \
9 komeda_dev.o \ 9 komeda_dev.o \
10 komeda_format_caps.o \ 10 komeda_format_caps.o \
11 komeda_pipeline.o 11 komeda_pipeline.o \
12 komeda_framebuffer.o
12 13
13komeda-y += \ 14komeda-y += \
14 d71/d71_dev.o 15 d71/d71_dev.o
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
new file mode 100644
index 000000000000..4ddd5314ca23
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
@@ -0,0 +1,165 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
5 *
6 */
7#include <drm/drm_gem.h>
8#include <drm/drm_gem_framebuffer_helper.h>
9#include <drm/drm_fb_cma_helper.h>
10#include <drm/drm_gem_cma_helper.h>
11#include "komeda_framebuffer.h"
12#include "komeda_dev.h"
13
14static void komeda_fb_destroy(struct drm_framebuffer *fb)
15{
16 struct komeda_fb *kfb = to_kfb(fb);
17 u32 i;
18
19 for (i = 0; i < fb->format->num_planes; i++)
20 drm_gem_object_put_unlocked(fb->obj[i]);
21
22 drm_framebuffer_cleanup(fb);
23 kfree(kfb);
24}
25
26static int komeda_fb_create_handle(struct drm_framebuffer *fb,
27 struct drm_file *file, u32 *handle)
28{
29 return drm_gem_handle_create(file, fb->obj[0], handle);
30}
31
32static const struct drm_framebuffer_funcs komeda_fb_funcs = {
33 .destroy = komeda_fb_destroy,
34 .create_handle = komeda_fb_create_handle,
35};
36
37static int
38komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb,
39 struct drm_file *file,
40 const struct drm_mode_fb_cmd2 *mode_cmd)
41{
42 struct drm_framebuffer *fb = &kfb->base;
43 struct drm_gem_object *obj;
44 u32 min_size = 0;
45 u32 i;
46
47 for (i = 0; i < fb->format->num_planes; i++) {
48 obj = drm_gem_object_lookup(file, mode_cmd->handles[i]);
49 if (!obj) {
50 DRM_DEBUG_KMS("Failed to lookup GEM object\n");
51 fb->obj[i] = NULL;
52
53 return -ENOENT;
54 }
55
56 kfb->aligned_w = fb->width / (i ? fb->format->hsub : 1);
57 kfb->aligned_h = fb->height / (i ? fb->format->vsub : 1);
58
59 if (fb->pitches[i] % mdev->chip.bus_width) {
60 DRM_DEBUG_KMS("Pitch[%d]: 0x%x doesn't align to 0x%x\n",
61 i, fb->pitches[i], mdev->chip.bus_width);
62 drm_gem_object_put_unlocked(obj);
63 fb->obj[i] = NULL;
64
65 return -EINVAL;
66 }
67
68 min_size = ((kfb->aligned_h / kfb->format_caps->tile_size - 1)
69 * fb->pitches[i])
70 + (kfb->aligned_w * fb->format->cpp[i]
71 * kfb->format_caps->tile_size)
72 + fb->offsets[i];
73
74 if (obj->size < min_size) {
75 DRM_DEBUG_KMS("Fail to check none afbc fb size.\n");
76 drm_gem_object_put_unlocked(obj);
77 fb->obj[i] = NULL;
78
79 return -EINVAL;
80 }
81
82 fb->obj[i] = obj;
83 }
84
85 if (fb->format->num_planes == 3) {
86 if (fb->pitches[1] != fb->pitches[2]) {
87 DRM_DEBUG_KMS("The pitch[1] and [2] are not same\n");
88 return -EINVAL;
89 }
90 }
91
92 return 0;
93}
94
95struct drm_framebuffer *
96komeda_fb_create(struct drm_device *dev, struct drm_file *file,
97 const struct drm_mode_fb_cmd2 *mode_cmd)
98{
99 struct komeda_dev *mdev = dev->dev_private;
100 struct komeda_fb *kfb;
101 int ret = 0, i;
102
103 kfb = kzalloc(sizeof(*kfb), GFP_KERNEL);
104 if (!kfb)
105 return ERR_PTR(-ENOMEM);
106
107 kfb->format_caps = komeda_get_format_caps(&mdev->fmt_tbl,
108 mode_cmd->pixel_format,
109 mode_cmd->modifier[0]);
110 if (!kfb->format_caps) {
111 DRM_DEBUG_KMS("FMT %x is not supported.\n",
112 mode_cmd->pixel_format);
113 kfree(kfb);
114 return ERR_PTR(-EINVAL);
115 }
116
117 drm_helper_mode_fill_fb_struct(dev, &kfb->base, mode_cmd);
118
119 ret = komeda_fb_none_afbc_size_check(mdev, kfb, file, mode_cmd);
120 if (ret < 0)
121 goto err_cleanup;
122
123 ret = drm_framebuffer_init(dev, &kfb->base, &komeda_fb_funcs);
124 if (ret < 0) {
125 DRM_DEBUG_KMS("failed to initialize fb\n");
126
127 goto err_cleanup;
128 }
129
130 return &kfb->base;
131
132err_cleanup:
133 for (i = 0; i < kfb->base.format->num_planes; i++)
134 drm_gem_object_put_unlocked(kfb->base.obj[i]);
135
136 kfree(kfb);
137 return ERR_PTR(ret);
138}
139
140dma_addr_t
141komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
142{
143 struct drm_framebuffer *fb = &kfb->base;
144 const struct drm_gem_cma_object *obj;
145 u32 plane_x, plane_y, cpp, pitch, offset;
146
147 if (plane > fb->format->num_planes) {
148 DRM_DEBUG_KMS("Out of max plane num.\n");
149 return -EINVAL;
150 }
151
152 obj = drm_fb_cma_get_gem_obj(fb, plane);
153
154 offset = fb->offsets[plane];
155 if (!fb->modifier) {
156 plane_x = x / (plane ? fb->format->hsub : 1);
157 plane_y = y / (plane ? fb->format->vsub : 1);
158 cpp = fb->format->cpp[plane];
159 pitch = fb->pitches[plane];
160 offset += plane_x * cpp * kfb->format_caps->tile_size +
161 (plane_y * pitch) / kfb->format_caps->tile_size;
162 }
163
164 return obj->paddr + offset;
165}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h
new file mode 100644
index 000000000000..0de2e4a2afd2
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h
@@ -0,0 +1,34 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
5 *
6 */
7#ifndef _KOMEDA_FRAMEBUFFER_H_
8#define _KOMEDA_FRAMEBUFFER_H_
9
10#include <drm/drm_framebuffer.h>
11#include "komeda_format_caps.h"
12
13/** struct komeda_fb - entend drm_framebuffer with komeda attribute */
14struct komeda_fb {
15 /** @base: &drm_framebuffer */
16 struct drm_framebuffer base;
17 /* @format_caps: &komeda_format_caps */
18 const struct komeda_format_caps *format_caps;
19 /** @aligned_w: aligned frame buffer width */
20 u32 aligned_w;
21 /** @aligned_h: aligned frame buffer height */
22 u32 aligned_h;
23};
24
25#define to_kfb(dfb) container_of(dfb, struct komeda_fb, base)
26
27struct drm_framebuffer *
28komeda_fb_create(struct drm_device *dev, struct drm_file *file,
29 const struct drm_mode_fb_cmd2 *mode_cmd);
30dma_addr_t
31komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane);
32bool komeda_fb_is_layer_supported(struct komeda_fb *kfb, u32 layer_type);
33
34#endif