blob: 00404ba4126ddcb787fdbc939755578c23875674 [file] [log] [blame]
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -08001// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright © 2018-2020 Intel Corporation
4 */
5
6#include <drm/drm_atomic.h>
7#include <drm/drm_atomic_helper.h>
8#include <drm/drm_crtc.h>
9#include <drm/drm_crtc_helper.h>
10#include <drm/drm_fb_cma_helper.h>
11#include <drm/drm_fb_helper.h>
12#include <drm/drm_fourcc.h>
13#include <drm/drm_gem_cma_helper.h>
14#include <drm/drm_managed.h>
15#include <drm/drm_plane_helper.h>
16
17#include "kmb_drv.h"
18#include "kmb_plane.h"
19#include "kmb_regs.h"
20
21const u32 layer_irqs[] = {
22 LCD_INT_VL0,
23 LCD_INT_VL1,
24 LCD_INT_GL0,
25 LCD_INT_GL1
26};
27
28/* Conversion (yuv->rgb) matrix from myriadx */
29static const u32 csc_coef_lcd[] = {
30 1024, 0, 1436,
31 1024, -352, -731,
32 1024, 1814, 0,
33 -179, 125, -226
34};
35
Anitha Chrisanthus7cb397e2020-11-10 13:52:49 -080036/* Graphics layer (layers 2 & 3) formats, only packed formats are supported */
37static const u32 kmb_formats_g[] = {
38 DRM_FORMAT_RGB332,
39 DRM_FORMAT_XRGB4444, DRM_FORMAT_XBGR4444,
40 DRM_FORMAT_ARGB4444, DRM_FORMAT_ABGR4444,
41 DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
42 DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
43 DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
44 DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
45 DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
46 DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
47};
48
49/* Video layer ( 0 & 1) formats, packed and planar formats are supported */
50static const u32 kmb_formats_v[] = {
51 /* packed formats */
52 DRM_FORMAT_RGB332,
53 DRM_FORMAT_XRGB4444, DRM_FORMAT_XBGR4444,
54 DRM_FORMAT_ARGB4444, DRM_FORMAT_ABGR4444,
55 DRM_FORMAT_XRGB1555, DRM_FORMAT_XBGR1555,
56 DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR1555,
57 DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
58 DRM_FORMAT_RGB888, DRM_FORMAT_BGR888,
59 DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
60 DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
61 /*planar formats */
62 DRM_FORMAT_YUV420, DRM_FORMAT_YVU420,
63 DRM_FORMAT_YUV422, DRM_FORMAT_YVU422,
64 DRM_FORMAT_YUV444, DRM_FORMAT_YVU444,
65 DRM_FORMAT_NV12, DRM_FORMAT_NV21,
66};
67
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -080068static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
69{
Edmund Dea982f8ad2021-10-06 16:03:48 -070070 struct kmb_drm_private *kmb;
71 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -080072 int i;
Edmund Dea982f8ad2021-10-06 16:03:48 -070073 int plane_id = kmb_plane->id;
74 struct disp_cfg init_disp_cfg;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -080075
Edmund Dea982f8ad2021-10-06 16:03:48 -070076 kmb = to_kmb(plane->dev);
77 init_disp_cfg = kmb->init_disp_cfg[plane_id];
78 /* Due to HW limitations, changing pixel format after initial
79 * plane configuration is not supported.
80 */
81 if (init_disp_cfg.format && init_disp_cfg.format != format) {
82 drm_dbg(&kmb->drm, "Cannot change format after initial plane configuration");
83 return -EINVAL;
84 }
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -080085 for (i = 0; i < plane->format_count; i++) {
86 if (plane->format_types[i] == format)
87 return 0;
88 }
89 return -EINVAL;
90}
91
92static int kmb_plane_atomic_check(struct drm_plane *plane,
Maxime Ripard7c11b992021-02-19 13:00:24 +010093 struct drm_atomic_state *state)
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -080094{
Maxime Ripard7c11b992021-02-19 13:00:24 +010095 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
96 plane);
Edmund Dea982f8ad2021-10-06 16:03:48 -070097 struct kmb_drm_private *kmb;
98 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
99 int plane_id = kmb_plane->id;
100 struct disp_cfg init_disp_cfg;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800101 struct drm_framebuffer *fb;
102 int ret;
103 struct drm_crtc_state *crtc_state;
104 bool can_position;
105
Edmund Dea982f8ad2021-10-06 16:03:48 -0700106 kmb = to_kmb(plane->dev);
107 init_disp_cfg = kmb->init_disp_cfg[plane_id];
Maxime Ripardba5c1642021-02-19 13:00:22 +0100108 fb = new_plane_state->fb;
109 if (!fb || !new_plane_state->crtc)
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800110 return 0;
111
112 ret = check_pixel_format(plane, fb->format->format);
113 if (ret)
114 return ret;
115
Edmund Deac0265652020-12-04 14:34:29 -0800116 if (new_plane_state->crtc_w > KMB_FB_MAX_WIDTH ||
117 new_plane_state->crtc_h > KMB_FB_MAX_HEIGHT ||
118 new_plane_state->crtc_w < KMB_FB_MIN_WIDTH ||
119 new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT)
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800120 return -EINVAL;
Edmund Dea982f8ad2021-10-06 16:03:48 -0700121
122 /* Due to HW limitations, changing plane height or width after
123 * initial plane configuration is not supported.
124 */
125 if ((init_disp_cfg.width && init_disp_cfg.height) &&
126 (init_disp_cfg.width != fb->width ||
127 init_disp_cfg.height != fb->height)) {
128 drm_dbg(&kmb->drm, "Cannot change plane height or width after initial configuration");
129 return -EINVAL;
130 }
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800131 can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
132 crtc_state =
Maxime Riparddec92022021-02-19 13:00:25 +0100133 drm_atomic_get_existing_crtc_state(state,
Maxime Ripardba5c1642021-02-19 13:00:22 +0100134 new_plane_state->crtc);
135 return drm_atomic_helper_check_plane_state(new_plane_state,
136 crtc_state,
137 DRM_PLANE_HELPER_NO_SCALING,
138 DRM_PLANE_HELPER_NO_SCALING,
139 can_position, true);
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800140}
141
142static void kmb_plane_atomic_disable(struct drm_plane *plane,
Maxime Ripard977697e2021-02-19 13:00:29 +0100143 struct drm_atomic_state *state)
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800144{
145 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
146 int plane_id = kmb_plane->id;
147 struct kmb_drm_private *kmb;
148
149 kmb = to_kmb(plane->dev);
150
Arnd Bergmann98fdd002020-11-29 21:09:08 +0100151 if (WARN_ON(plane_id >= KMB_MAX_PLANES))
152 return;
153
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800154 switch (plane_id) {
155 case LAYER_0:
156 kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL1_ENABLE;
157 break;
158 case LAYER_1:
159 kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE;
160 break;
161 case LAYER_2:
162 kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL1_ENABLE;
163 break;
164 case LAYER_3:
165 kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL2_ENABLE;
166 break;
167 }
168
169 kmb->plane_status[plane_id].disable = true;
170}
171
172static unsigned int get_pixel_format(u32 format)
173{
174 unsigned int val = 0;
175
176 switch (format) {
177 /* planar formats */
178 case DRM_FORMAT_YUV444:
179 val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE;
180 break;
181 case DRM_FORMAT_YVU444:
182 val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE
183 | LCD_LAYER_CRCB_ORDER;
184 break;
185 case DRM_FORMAT_YUV422:
186 val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE;
187 break;
188 case DRM_FORMAT_YVU422:
189 val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE
190 | LCD_LAYER_CRCB_ORDER;
191 break;
192 case DRM_FORMAT_YUV420:
193 val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE;
194 break;
195 case DRM_FORMAT_YVU420:
196 val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE
197 | LCD_LAYER_CRCB_ORDER;
198 break;
199 case DRM_FORMAT_NV12:
200 val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE;
201 break;
202 case DRM_FORMAT_NV21:
203 val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
204 | LCD_LAYER_CRCB_ORDER;
205 break;
206 /* packed formats */
207 /* looks hw requires B & G to be swapped when RGB */
208 case DRM_FORMAT_RGB332:
209 val = LCD_LAYER_FORMAT_RGB332 | LCD_LAYER_BGR_ORDER;
210 break;
211 case DRM_FORMAT_XBGR4444:
212 val = LCD_LAYER_FORMAT_RGBX4444;
213 break;
214 case DRM_FORMAT_ARGB4444:
215 val = LCD_LAYER_FORMAT_RGBA4444 | LCD_LAYER_BGR_ORDER;
216 break;
217 case DRM_FORMAT_ABGR4444:
218 val = LCD_LAYER_FORMAT_RGBA4444;
219 break;
220 case DRM_FORMAT_XRGB1555:
221 val = LCD_LAYER_FORMAT_XRGB1555 | LCD_LAYER_BGR_ORDER;
222 break;
223 case DRM_FORMAT_XBGR1555:
224 val = LCD_LAYER_FORMAT_XRGB1555;
225 break;
226 case DRM_FORMAT_ARGB1555:
227 val = LCD_LAYER_FORMAT_RGBA1555 | LCD_LAYER_BGR_ORDER;
228 break;
229 case DRM_FORMAT_ABGR1555:
230 val = LCD_LAYER_FORMAT_RGBA1555;
231 break;
232 case DRM_FORMAT_RGB565:
233 val = LCD_LAYER_FORMAT_RGB565 | LCD_LAYER_BGR_ORDER;
234 break;
235 case DRM_FORMAT_BGR565:
236 val = LCD_LAYER_FORMAT_RGB565;
237 break;
238 case DRM_FORMAT_RGB888:
239 val = LCD_LAYER_FORMAT_RGB888 | LCD_LAYER_BGR_ORDER;
240 break;
241 case DRM_FORMAT_BGR888:
242 val = LCD_LAYER_FORMAT_RGB888;
243 break;
244 case DRM_FORMAT_XRGB8888:
245 val = LCD_LAYER_FORMAT_RGBX8888 | LCD_LAYER_BGR_ORDER;
246 break;
247 case DRM_FORMAT_XBGR8888:
248 val = LCD_LAYER_FORMAT_RGBX8888;
249 break;
250 case DRM_FORMAT_ARGB8888:
251 val = LCD_LAYER_FORMAT_RGBA8888 | LCD_LAYER_BGR_ORDER;
252 break;
253 case DRM_FORMAT_ABGR8888:
254 val = LCD_LAYER_FORMAT_RGBA8888;
255 break;
256 }
257 DRM_INFO_ONCE("%s : %d format=0x%x val=0x%x\n",
258 __func__, __LINE__, format, val);
259 return val;
260}
261
262static unsigned int get_bits_per_pixel(const struct drm_format_info *format)
263{
264 u32 bpp = 0;
265 unsigned int val = 0;
266
267 if (format->num_planes > 1) {
268 val = LCD_LAYER_8BPP;
269 return val;
270 }
271
272 bpp += 8 * format->cpp[0];
273
274 switch (bpp) {
275 case 8:
276 val = LCD_LAYER_8BPP;
277 break;
278 case 16:
279 val = LCD_LAYER_16BPP;
280 break;
281 case 24:
282 val = LCD_LAYER_24BPP;
283 break;
284 case 32:
285 val = LCD_LAYER_32BPP;
286 break;
287 }
288
289 DRM_DEBUG("bpp=%d val=0x%x\n", bpp, val);
290 return val;
291}
292
293static void config_csc(struct kmb_drm_private *kmb, int plane_id)
294{
295 /* YUV to RGB conversion using the fixed matrix csc_coef_lcd */
296 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF11(plane_id), csc_coef_lcd[0]);
297 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF12(plane_id), csc_coef_lcd[1]);
298 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF13(plane_id), csc_coef_lcd[2]);
299 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF21(plane_id), csc_coef_lcd[3]);
300 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF22(plane_id), csc_coef_lcd[4]);
301 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF23(plane_id), csc_coef_lcd[5]);
302 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF31(plane_id), csc_coef_lcd[6]);
303 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF32(plane_id), csc_coef_lcd[7]);
304 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF33(plane_id), csc_coef_lcd[8]);
305 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF1(plane_id), csc_coef_lcd[9]);
306 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF2(plane_id), csc_coef_lcd[10]);
307 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]);
308}
309
Edmund Deac0265652020-12-04 14:34:29 -0800310static void kmb_plane_set_alpha(struct kmb_drm_private *kmb,
311 const struct drm_plane_state *state,
312 unsigned char plane_id,
313 unsigned int *val)
314{
315 u16 plane_alpha = state->alpha;
316 u16 pixel_blend_mode = state->pixel_blend_mode;
317 int has_alpha = state->fb->format->has_alpha;
318
319 if (plane_alpha != DRM_BLEND_ALPHA_OPAQUE)
320 *val |= LCD_LAYER_ALPHA_STATIC;
321
322 if (has_alpha) {
323 switch (pixel_blend_mode) {
324 case DRM_MODE_BLEND_PIXEL_NONE:
325 break;
326 case DRM_MODE_BLEND_PREMULTI:
327 *val |= LCD_LAYER_ALPHA_EMBED | LCD_LAYER_ALPHA_PREMULT;
328 break;
329 case DRM_MODE_BLEND_COVERAGE:
330 *val |= LCD_LAYER_ALPHA_EMBED;
331 break;
332 default:
333 DRM_DEBUG("Missing pixel blend mode case (%s == %ld)\n",
334 __stringify(pixel_blend_mode),
335 (long)pixel_blend_mode);
336 break;
337 }
338 }
339
340 if (plane_alpha == DRM_BLEND_ALPHA_OPAQUE && !has_alpha) {
341 *val &= LCD_LAYER_ALPHA_DISABLED;
342 return;
343 }
344
345 kmb_write_lcd(kmb, LCD_LAYERn_ALPHA(plane_id), plane_alpha);
346}
347
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800348static void kmb_plane_atomic_update(struct drm_plane *plane,
Maxime Ripard977697e2021-02-19 13:00:29 +0100349 struct drm_atomic_state *state)
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800350{
Maxime Ripard977697e2021-02-19 13:00:29 +0100351 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state,
352 plane);
Maxime Ripard37418bf2021-02-19 13:00:30 +0100353 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
354 plane);
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800355 struct drm_framebuffer *fb;
356 struct kmb_drm_private *kmb;
357 unsigned int width;
358 unsigned int height;
359 unsigned int dma_len;
360 struct kmb_plane *kmb_plane;
361 unsigned int dma_cfg;
362 unsigned int ctrl = 0, val = 0, out_format = 0;
363 unsigned int src_w, src_h, crtc_x, crtc_y;
364 unsigned char plane_id;
365 int num_planes;
366 static dma_addr_t addr[MAX_SUB_PLANES];
Edmund Dea982f8ad2021-10-06 16:03:48 -0700367 struct disp_cfg *init_disp_cfg;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800368
Maxime Ripard977697e2021-02-19 13:00:29 +0100369 if (!plane || !new_plane_state || !old_plane_state)
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800370 return;
371
Maxime Riparde05162c02021-02-19 13:00:27 +0100372 fb = new_plane_state->fb;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800373 if (!fb)
374 return;
Edmund Deac0265652020-12-04 14:34:29 -0800375
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800376 num_planes = fb->format->num_planes;
377 kmb_plane = to_kmb_plane(plane);
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800378
379 kmb = to_kmb(plane->dev);
Edmund Deac0265652020-12-04 14:34:29 -0800380 plane_id = kmb_plane->id;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800381
382 spin_lock_irq(&kmb->irq_lock);
383 if (kmb->kmb_under_flow || kmb->kmb_flush_done) {
384 spin_unlock_irq(&kmb->irq_lock);
385 drm_dbg(&kmb->drm, "plane_update:underflow!!!! returning");
386 return;
387 }
388 spin_unlock_irq(&kmb->irq_lock);
389
Edmund Dea982f8ad2021-10-06 16:03:48 -0700390 init_disp_cfg = &kmb->init_disp_cfg[plane_id];
391 src_w = new_plane_state->src_w >> 16;
Maxime Riparde05162c02021-02-19 13:00:27 +0100392 src_h = new_plane_state->src_h >> 16;
393 crtc_x = new_plane_state->crtc_x;
394 crtc_y = new_plane_state->crtc_y;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800395
396 drm_dbg(&kmb->drm,
397 "src_w=%d src_h=%d, fb->format->format=0x%x fb->flags=0x%x\n",
398 src_w, src_h, fb->format->format, fb->flags);
399
400 width = fb->width;
401 height = fb->height;
402 dma_len = (width * height * fb->format->cpp[0]);
403 drm_dbg(&kmb->drm, "dma_len=%d ", dma_len);
404 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN(plane_id), dma_len);
405 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN_SHADOW(plane_id), dma_len);
406 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
407 fb->pitches[0]);
408 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),
409 (width * fb->format->cpp[0]));
410
Maxime Riparde05162c02021-02-19 13:00:27 +0100411 addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0);
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800412 kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id),
413 addr[Y_PLANE] + fb->offsets[0]);
414 val = get_pixel_format(fb->format->format);
415 val |= get_bits_per_pixel(fb->format);
416 /* Program Cb/Cr for planar formats */
417 if (num_planes > 1) {
418 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
419 width * fb->format->cpp[0]);
420 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
421 (width * fb->format->cpp[0]));
422
Maxime Riparde05162c02021-02-19 13:00:27 +0100423 addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state,
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800424 U_PLANE);
425 /* check if Cb/Cr is swapped*/
426 if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER))
427 kmb_write_lcd(kmb,
428 LCD_LAYERn_DMA_START_CR_ADR(plane_id),
429 addr[U_PLANE]);
430 else
431 kmb_write_lcd(kmb,
432 LCD_LAYERn_DMA_START_CB_ADR(plane_id),
433 addr[U_PLANE]);
434
435 if (num_planes == 3) {
436 kmb_write_lcd(kmb,
437 LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
438 ((width) * fb->format->cpp[0]));
439
440 kmb_write_lcd(kmb,
441 LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
442 ((width) * fb->format->cpp[0]));
443
444 addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb,
Maxime Riparde05162c02021-02-19 13:00:27 +0100445 new_plane_state,
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800446 V_PLANE);
447
448 /* check if Cb/Cr is swapped*/
449 if (val & LCD_LAYER_CRCB_ORDER)
450 kmb_write_lcd(kmb,
451 LCD_LAYERn_DMA_START_CB_ADR(plane_id),
452 addr[V_PLANE]);
453 else
454 kmb_write_lcd(kmb,
455 LCD_LAYERn_DMA_START_CR_ADR(plane_id),
456 addr[V_PLANE]);
457 }
458 }
459
460 kmb_write_lcd(kmb, LCD_LAYERn_WIDTH(plane_id), src_w - 1);
461 kmb_write_lcd(kmb, LCD_LAYERn_HEIGHT(plane_id), src_h - 1);
462 kmb_write_lcd(kmb, LCD_LAYERn_COL_START(plane_id), crtc_x);
463 kmb_write_lcd(kmb, LCD_LAYERn_ROW_START(plane_id), crtc_y);
464
465 val |= LCD_LAYER_FIFO_100;
466
467 if (val & LCD_LAYER_PLANAR_STORAGE) {
468 val |= LCD_LAYER_CSC_EN;
469
470 /* Enable CSC if input is planar and output is RGB */
471 config_csc(kmb, plane_id);
472 }
473
Edmund Deac0265652020-12-04 14:34:29 -0800474 kmb_plane_set_alpha(kmb, plane->state, plane_id, &val);
475
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800476 kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val);
477
Edmund Deac0265652020-12-04 14:34:29 -0800478 /* Configure LCD_CONTROL */
479 ctrl = kmb_read_lcd(kmb, LCD_CONTROL);
480
481 /* Set layer blending config */
482 ctrl &= ~LCD_CTRL_ALPHA_ALL;
483 ctrl |= LCD_CTRL_ALPHA_BOTTOM_VL1 |
484 LCD_CTRL_ALPHA_BLEND_VL2;
485
486 ctrl &= ~LCD_CTRL_ALPHA_BLEND_BKGND_DISABLE;
487
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800488 switch (plane_id) {
489 case LAYER_0:
Edmund Deac0265652020-12-04 14:34:29 -0800490 ctrl |= LCD_CTRL_VL1_ENABLE;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800491 break;
492 case LAYER_1:
Edmund Deac0265652020-12-04 14:34:29 -0800493 ctrl |= LCD_CTRL_VL2_ENABLE;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800494 break;
495 case LAYER_2:
Edmund Deac0265652020-12-04 14:34:29 -0800496 ctrl |= LCD_CTRL_GL1_ENABLE;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800497 break;
498 case LAYER_3:
Edmund Deac0265652020-12-04 14:34:29 -0800499 ctrl |= LCD_CTRL_GL2_ENABLE;
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800500 break;
501 }
502
503 ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
504 | LCD_CTRL_CONTINUOUS | LCD_CTRL_OUTPUT_ENABLED;
505
506 /* LCD is connected to MIPI on kmb
507 * Therefore this bit is required for DSI Tx
508 */
509 ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
510
Edmund Deac0265652020-12-04 14:34:29 -0800511 kmb_write_lcd(kmb, LCD_CONTROL, ctrl);
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800512
Edmund Dea0aab5dc2020-08-25 14:51:17 -0700513 /* Enable pipeline AXI read transactions for the DMA
514 * after setting graphics layers. This must be done
515 * in a separate write cycle.
516 */
517 kmb_set_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
518
519 /* FIXME no doc on how to set output format, these values are taken
520 * from the Myriadx tests
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800521 */
522 out_format |= LCD_OUTF_FORMAT_RGB888;
523
524 /* Leave RGB order,conversion mode and clip mode to default */
525 /* do not interleave RGB channels for mipi Tx compatibility */
526 out_format |= LCD_OUTF_MIPI_RGB_MODE;
527 kmb_write_lcd(kmb, LCD_OUT_FORMAT_CFG, out_format);
528
529 dma_cfg = LCD_DMA_LAYER_ENABLE | LCD_DMA_LAYER_VSTRIDE_EN |
530 LCD_DMA_LAYER_CONT_UPDATE | LCD_DMA_LAYER_AXI_BURST_16;
531
532 /* Enable DMA */
533 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
Edmund Dea982f8ad2021-10-06 16:03:48 -0700534
535 /* Save initial display config */
536 if (!init_disp_cfg->width ||
537 !init_disp_cfg->height ||
538 !init_disp_cfg->format) {
539 init_disp_cfg->width = width;
540 init_disp_cfg->height = height;
541 init_disp_cfg->format = fb->format->format;
542 }
543
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800544 drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg,
545 kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id)));
546
547 kmb_set_bitmask_lcd(kmb, LCD_INT_CLEAR, LCD_INT_EOF |
548 LCD_INT_DMA_ERR);
549 kmb_set_bitmask_lcd(kmb, LCD_INT_ENABLE, LCD_INT_EOF |
550 LCD_INT_DMA_ERR);
551}
552
553static const struct drm_plane_helper_funcs kmb_plane_helper_funcs = {
554 .atomic_check = kmb_plane_atomic_check,
555 .atomic_update = kmb_plane_atomic_update,
556 .atomic_disable = kmb_plane_atomic_disable
557};
558
559void kmb_plane_destroy(struct drm_plane *plane)
560{
561 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
562
563 drm_plane_cleanup(plane);
564 kfree(kmb_plane);
565}
566
567static const struct drm_plane_funcs kmb_plane_funcs = {
568 .update_plane = drm_atomic_helper_update_plane,
569 .disable_plane = drm_atomic_helper_disable_plane,
570 .destroy = kmb_plane_destroy,
571 .reset = drm_atomic_helper_plane_reset,
572 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
573 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
574};
575
576struct kmb_plane *kmb_plane_init(struct drm_device *drm)
577{
578 struct kmb_drm_private *kmb = to_kmb(drm);
579 struct kmb_plane *plane = NULL;
580 struct kmb_plane *primary = NULL;
581 int i = 0;
582 int ret = 0;
583 enum drm_plane_type plane_type;
584 const u32 *plane_formats;
585 int num_plane_formats;
Edmund Deac0265652020-12-04 14:34:29 -0800586 unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
587 BIT(DRM_MODE_BLEND_PREMULTI) |
588 BIT(DRM_MODE_BLEND_COVERAGE);
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800589
590 for (i = 0; i < KMB_MAX_PLANES; i++) {
591 plane = drmm_kzalloc(drm, sizeof(*plane), GFP_KERNEL);
592
593 if (!plane) {
594 drm_err(drm, "Failed to allocate plane\n");
595 return ERR_PTR(-ENOMEM);
596 }
597
598 plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
599 DRM_PLANE_TYPE_OVERLAY;
600 if (i < 2) {
601 plane_formats = kmb_formats_v;
602 num_plane_formats = ARRAY_SIZE(kmb_formats_v);
603 } else {
604 plane_formats = kmb_formats_g;
605 num_plane_formats = ARRAY_SIZE(kmb_formats_g);
606 }
607
608 ret = drm_universal_plane_init(drm, &plane->base_plane,
609 POSSIBLE_CRTCS, &kmb_plane_funcs,
610 plane_formats, num_plane_formats,
611 NULL, plane_type, "plane %d", i);
612 if (ret < 0) {
613 drm_err(drm, "drm_universal_plane_init failed (ret=%d)",
614 ret);
615 goto cleanup;
616 }
617 drm_dbg(drm, "%s : %d i=%d type=%d",
618 __func__, __LINE__,
619 i, plane_type);
Edmund Deac0265652020-12-04 14:34:29 -0800620 drm_plane_create_alpha_property(&plane->base_plane);
621
622 drm_plane_create_blend_mode_property(&plane->base_plane,
623 blend_caps);
624
625 drm_plane_create_zpos_immutable_property(&plane->base_plane, i);
626
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800627 drm_plane_helper_add(&plane->base_plane,
628 &kmb_plane_helper_funcs);
Edmund Deac0265652020-12-04 14:34:29 -0800629
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800630 if (plane_type == DRM_PLANE_TYPE_PRIMARY) {
631 primary = plane;
632 kmb->plane = plane;
633 }
634 drm_dbg(drm, "%s : %d primary=%p\n", __func__, __LINE__,
635 &primary->base_plane);
636 plane->id = i;
637 }
638
Edmund Dea0aab5dc2020-08-25 14:51:17 -0700639 /* Disable pipeline AXI read transactions for the DMA
640 * prior to setting graphics layers
641 */
642 kmb_clr_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
643
Anitha Chrisanthus7f7b96a2020-11-04 17:15:29 -0800644 return primary;
645cleanup:
646 drmm_kfree(drm, plane);
647 return ERR_PTR(ret);
648}