]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/gpu/drm/zte/zx_plane.c
drm: Nuke fb->pixel_format
[mirror_ubuntu-jammy-kernel.git] / drivers / gpu / drm / zte / zx_plane.c
CommitLineData
0a886f59
SG
1/*
2 * Copyright 2016 Linaro Ltd.
3 * Copyright 2016 ZTE Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <drm/drm_atomic.h>
12#include <drm/drm_atomic_helper.h>
13#include <drm/drm_fb_cma_helper.h>
14#include <drm/drm_gem_cma_helper.h>
15#include <drm/drm_modeset_helper_vtables.h>
16#include <drm/drm_plane_helper.h>
17#include <drm/drmP.h>
18
19#include "zx_drm_drv.h"
20#include "zx_plane.h"
21#include "zx_plane_regs.h"
22#include "zx_vou.h"
23
24struct zx_plane {
25 struct drm_plane plane;
26 void __iomem *layer;
27 void __iomem *csc;
28 void __iomem *hbsc;
29 void __iomem *rsz;
30};
31
32#define to_zx_plane(plane) container_of(plane, struct zx_plane, plane)
33
34static const uint32_t gl_formats[] = {
35 DRM_FORMAT_ARGB8888,
36 DRM_FORMAT_XRGB8888,
37 DRM_FORMAT_RGB888,
38 DRM_FORMAT_RGB565,
39 DRM_FORMAT_ARGB1555,
40 DRM_FORMAT_ARGB4444,
41};
42
43static int zx_gl_plane_atomic_check(struct drm_plane *plane,
44 struct drm_plane_state *plane_state)
45{
46 struct drm_framebuffer *fb = plane_state->fb;
47 struct drm_crtc *crtc = plane_state->crtc;
48 struct drm_crtc_state *crtc_state;
49 struct drm_rect clip;
50
51 if (!crtc || !fb)
52 return 0;
53
54 crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
55 crtc);
56 if (WARN_ON(!crtc_state))
57 return -EINVAL;
58
59 /* nothing to check when disabling or disabled */
60 if (!crtc_state->enable)
61 return 0;
62
63 /* plane must be enabled */
64 if (!plane_state->crtc)
65 return -EINVAL;
66
67 clip.x1 = 0;
68 clip.y1 = 0;
69 clip.x2 = crtc_state->adjusted_mode.hdisplay;
70 clip.y2 = crtc_state->adjusted_mode.vdisplay;
71
72 return drm_plane_helper_check_state(plane_state, &clip,
73 DRM_PLANE_HELPER_NO_SCALING,
74 DRM_PLANE_HELPER_NO_SCALING,
75 false, true);
76}
77
78static int zx_gl_get_fmt(uint32_t format)
79{
80 switch (format) {
81 case DRM_FORMAT_ARGB8888:
82 case DRM_FORMAT_XRGB8888:
83 return GL_FMT_ARGB8888;
84 case DRM_FORMAT_RGB888:
85 return GL_FMT_RGB888;
86 case DRM_FORMAT_RGB565:
87 return GL_FMT_RGB565;
88 case DRM_FORMAT_ARGB1555:
89 return GL_FMT_ARGB1555;
90 case DRM_FORMAT_ARGB4444:
91 return GL_FMT_ARGB4444;
92 default:
93 WARN_ONCE(1, "invalid pixel format %d\n", format);
94 return -EINVAL;
95 }
96}
97
98static inline void zx_gl_set_update(struct zx_plane *zplane)
99{
100 void __iomem *layer = zplane->layer;
101
102 zx_writel_mask(layer + GL_CTRL0, GL_UPDATE, GL_UPDATE);
103}
104
105static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
106{
107 zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
108}
109
110void zx_plane_set_update(struct drm_plane *plane)
111{
112 struct zx_plane *zplane = to_zx_plane(plane);
113
114 zx_gl_rsz_set_update(zplane);
115 zx_gl_set_update(zplane);
116}
117
118static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
119 u32 dst_w, u32 dst_h)
120{
121 void __iomem *rsz = zplane->rsz;
122
123 zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
124 zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
125
126 zx_gl_rsz_set_update(zplane);
127}
128
129static void zx_gl_plane_atomic_update(struct drm_plane *plane,
130 struct drm_plane_state *old_state)
131{
132 struct zx_plane *zplane = to_zx_plane(plane);
133 struct drm_framebuffer *fb = plane->state->fb;
134 struct drm_gem_cma_object *cma_obj;
135 void __iomem *layer = zplane->layer;
136 void __iomem *csc = zplane->csc;
137 void __iomem *hbsc = zplane->hbsc;
138 u32 src_x, src_y, src_w, src_h;
139 u32 dst_x, dst_y, dst_w, dst_h;
d8c1abd9 140 unsigned int bpp;
0a886f59
SG
141 uint32_t format;
142 dma_addr_t paddr;
143 u32 stride;
144 int fmt;
145
146 if (!fb)
147 return;
148
438b74a5 149 format = fb->format->format;
0a886f59
SG
150 stride = fb->pitches[0];
151
152 src_x = plane->state->src_x >> 16;
153 src_y = plane->state->src_y >> 16;
154 src_w = plane->state->src_w >> 16;
155 src_h = plane->state->src_h >> 16;
156
157 dst_x = plane->state->crtc_x;
158 dst_y = plane->state->crtc_y;
159 dst_w = plane->state->crtc_w;
160 dst_h = plane->state->crtc_h;
161
353c8598 162 bpp = fb->format->cpp[0];
0a886f59
SG
163
164 cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
165 paddr = cma_obj->paddr + fb->offsets[0];
166 paddr += src_y * stride + src_x * bpp / 8;
167 zx_writel(layer + GL_ADDR, paddr);
168
169 /* Set up source height/width register */
170 zx_writel(layer + GL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
171
172 /* Set up start position register */
173 zx_writel(layer + GL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
174
175 /* Set up end position register */
176 zx_writel(layer + GL_POS_END,
177 GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
178
179 /* Set up stride register */
180 zx_writel(layer + GL_STRIDE, stride & 0xffff);
181
182 /* Set up graphic layer data format */
183 fmt = zx_gl_get_fmt(format);
184 if (fmt >= 0)
185 zx_writel_mask(layer + GL_CTRL1, GL_DATA_FMT_MASK,
186 fmt << GL_DATA_FMT_SHIFT);
187
188 /* Initialize global alpha with a sane value */
189 zx_writel_mask(layer + GL_CTRL2, GL_GLOBAL_ALPHA_MASK,
190 0xff << GL_GLOBAL_ALPHA_SHIFT);
191
192 /* Setup CSC for the GL */
193 if (dst_h > 720)
194 zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
195 CSC_BT709_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
196 else
197 zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
198 CSC_BT601_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
199 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, CSC_WORK_ENABLE);
200
201 /* Always use scaler since it exists (set for not bypass) */
202 zx_writel_mask(layer + GL_CTRL3, GL_SCALER_BYPASS_MODE,
203 GL_SCALER_BYPASS_MODE);
204
205 zx_gl_rsz_setup(zplane, src_w, src_h, dst_w, dst_h);
206
207 /* Enable HBSC block */
208 zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
209
210 zx_gl_set_update(zplane);
211}
212
213static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
214 .atomic_check = zx_gl_plane_atomic_check,
215 .atomic_update = zx_gl_plane_atomic_update,
216};
217
218static void zx_plane_destroy(struct drm_plane *plane)
219{
220 drm_plane_helper_disable(plane);
221 drm_plane_cleanup(plane);
222}
223
224static const struct drm_plane_funcs zx_plane_funcs = {
225 .update_plane = drm_atomic_helper_update_plane,
226 .disable_plane = drm_atomic_helper_disable_plane,
227 .destroy = zx_plane_destroy,
228 .reset = drm_atomic_helper_plane_reset,
229 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
230 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
231};
232
233static void zx_plane_hbsc_init(struct zx_plane *zplane)
234{
235 void __iomem *hbsc = zplane->hbsc;
236
237 /*
238 * Initialize HBSC block with a sane configuration per recommedation
239 * from ZTE BSP code.
240 */
241 zx_writel(hbsc + HBSC_SATURATION, 0x200);
242 zx_writel(hbsc + HBSC_HUE, 0x0);
243 zx_writel(hbsc + HBSC_BRIGHT, 0x0);
244 zx_writel(hbsc + HBSC_CONTRAST, 0x200);
245
246 zx_writel(hbsc + HBSC_THRESHOLD_COL1, (0x3ac << 16) | 0x40);
247 zx_writel(hbsc + HBSC_THRESHOLD_COL2, (0x3c0 << 16) | 0x40);
248 zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40);
249}
250
251struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
252 struct zx_layer_data *data,
253 enum drm_plane_type type)
254{
255 const struct drm_plane_helper_funcs *helper;
256 struct zx_plane *zplane;
257 struct drm_plane *plane;
258 const uint32_t *formats;
259 unsigned int format_count;
260 int ret;
261
262 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
263 if (!zplane)
264 return ERR_PTR(-ENOMEM);
265
266 plane = &zplane->plane;
267
268 zplane->layer = data->layer;
269 zplane->hbsc = data->hbsc;
270 zplane->csc = data->csc;
271 zplane->rsz = data->rsz;
272
273 zx_plane_hbsc_init(zplane);
274
275 switch (type) {
276 case DRM_PLANE_TYPE_PRIMARY:
277 helper = &zx_gl_plane_helper_funcs;
278 formats = gl_formats;
279 format_count = ARRAY_SIZE(gl_formats);
280 break;
281 case DRM_PLANE_TYPE_OVERLAY:
282 /* TODO: add video layer (vl) support */
283 break;
284 default:
285 return ERR_PTR(-ENODEV);
286 }
287
288 ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
289 &zx_plane_funcs, formats, format_count,
290 type, NULL);
291 if (ret) {
292 DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
293 return ERR_PTR(ret);
294 }
295
296 drm_plane_helper_add(plane, helper);
297
298 return plane;
299}