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

source code of linux/drivers/gpu/drm/kmb/kmb_plane.c