Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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_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
36/* 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
68static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
69{
70 int i;
71
72 for (i = 0; i < plane->format_count; i++) {
73 if (plane->format_types[i] == format)
74 return 0;
75 }
76 return -EINVAL;
77}
78
79static int kmb_plane_atomic_check(struct drm_plane *plane,
80 struct drm_plane_state *state)
81{
82 struct drm_framebuffer *fb;
83 int ret;
84 struct drm_crtc_state *crtc_state;
85 bool can_position;
86
87 fb = state->fb;
88 if (!fb || !state->crtc)
89 return 0;
90
91 ret = check_pixel_format(plane, fb->format->format);
92 if (ret)
93 return ret;
94
95 if (state->crtc_w > KMB_MAX_WIDTH || state->crtc_h > KMB_MAX_HEIGHT)
96 return -EINVAL;
97 if (state->crtc_w < KMB_MIN_WIDTH || state->crtc_h < KMB_MIN_HEIGHT)
98 return -EINVAL;
99 can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
100 crtc_state =
101 drm_atomic_get_existing_crtc_state(state->state, state->crtc);
102 return drm_atomic_helper_check_plane_state(state, crtc_state,
103 DRM_PLANE_HELPER_NO_SCALING,
104 DRM_PLANE_HELPER_NO_SCALING,
105 can_position, true);
106}
107
108static void kmb_plane_atomic_disable(struct drm_plane *plane,
109 struct drm_plane_state *state)
110{
111 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
112 int plane_id = kmb_plane->id;
113 struct kmb_drm_private *kmb;
114
115 kmb = to_kmb(plane->dev);
116
117 if (WARN_ON(plane_id >= KMB_MAX_PLANES))
118 return;
119
120 switch (plane_id) {
121 case LAYER_0:
122 kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL1_ENABLE;
123 break;
124 case LAYER_1:
125 kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE;
126 break;
127 case LAYER_2:
128 kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL1_ENABLE;
129 break;
130 case LAYER_3:
131 kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL2_ENABLE;
132 break;
133 }
134
135 kmb->plane_status[plane_id].disable = true;
136}
137
138static unsigned int get_pixel_format(u32 format)
139{
140 unsigned int val = 0;
141
142 switch (format) {
143 /* planar formats */
144 case DRM_FORMAT_YUV444:
145 val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE;
146 break;
147 case DRM_FORMAT_YVU444:
148 val = LCD_LAYER_FORMAT_YCBCR444PLAN | LCD_LAYER_PLANAR_STORAGE
149 | LCD_LAYER_CRCB_ORDER;
150 break;
151 case DRM_FORMAT_YUV422:
152 val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE;
153 break;
154 case DRM_FORMAT_YVU422:
155 val = LCD_LAYER_FORMAT_YCBCR422PLAN | LCD_LAYER_PLANAR_STORAGE
156 | LCD_LAYER_CRCB_ORDER;
157 break;
158 case DRM_FORMAT_YUV420:
159 val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE;
160 break;
161 case DRM_FORMAT_YVU420:
162 val = LCD_LAYER_FORMAT_YCBCR420PLAN | LCD_LAYER_PLANAR_STORAGE
163 | LCD_LAYER_CRCB_ORDER;
164 break;
165 case DRM_FORMAT_NV12:
166 val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE;
167 break;
168 case DRM_FORMAT_NV21:
169 val = LCD_LAYER_FORMAT_NV12 | LCD_LAYER_PLANAR_STORAGE
170 | LCD_LAYER_CRCB_ORDER;
171 break;
172 /* packed formats */
173 /* looks hw requires B & G to be swapped when RGB */
174 case DRM_FORMAT_RGB332:
175 val = LCD_LAYER_FORMAT_RGB332 | LCD_LAYER_BGR_ORDER;
176 break;
177 case DRM_FORMAT_XBGR4444:
178 val = LCD_LAYER_FORMAT_RGBX4444;
179 break;
180 case DRM_FORMAT_ARGB4444:
181 val = LCD_LAYER_FORMAT_RGBA4444 | LCD_LAYER_BGR_ORDER;
182 break;
183 case DRM_FORMAT_ABGR4444:
184 val = LCD_LAYER_FORMAT_RGBA4444;
185 break;
186 case DRM_FORMAT_XRGB1555:
187 val = LCD_LAYER_FORMAT_XRGB1555 | LCD_LAYER_BGR_ORDER;
188 break;
189 case DRM_FORMAT_XBGR1555:
190 val = LCD_LAYER_FORMAT_XRGB1555;
191 break;
192 case DRM_FORMAT_ARGB1555:
193 val = LCD_LAYER_FORMAT_RGBA1555 | LCD_LAYER_BGR_ORDER;
194 break;
195 case DRM_FORMAT_ABGR1555:
196 val = LCD_LAYER_FORMAT_RGBA1555;
197 break;
198 case DRM_FORMAT_RGB565:
199 val = LCD_LAYER_FORMAT_RGB565 | LCD_LAYER_BGR_ORDER;
200 break;
201 case DRM_FORMAT_BGR565:
202 val = LCD_LAYER_FORMAT_RGB565;
203 break;
204 case DRM_FORMAT_RGB888:
205 val = LCD_LAYER_FORMAT_RGB888 | LCD_LAYER_BGR_ORDER;
206 break;
207 case DRM_FORMAT_BGR888:
208 val = LCD_LAYER_FORMAT_RGB888;
209 break;
210 case DRM_FORMAT_XRGB8888:
211 val = LCD_LAYER_FORMAT_RGBX8888 | LCD_LAYER_BGR_ORDER;
212 break;
213 case DRM_FORMAT_XBGR8888:
214 val = LCD_LAYER_FORMAT_RGBX8888;
215 break;
216 case DRM_FORMAT_ARGB8888:
217 val = LCD_LAYER_FORMAT_RGBA8888 | LCD_LAYER_BGR_ORDER;
218 break;
219 case DRM_FORMAT_ABGR8888:
220 val = LCD_LAYER_FORMAT_RGBA8888;
221 break;
222 }
223 DRM_INFO_ONCE("%s : %d format=0x%x val=0x%x\n",
224 __func__, __LINE__, format, val);
225 return val;
226}
227
228static unsigned int get_bits_per_pixel(const struct drm_format_info *format)
229{
230 u32 bpp = 0;
231 unsigned int val = 0;
232
233 if (format->num_planes > 1) {
234 val = LCD_LAYER_8BPP;
235 return val;
236 }
237
238 bpp += 8 * format->cpp[0];
239
240 switch (bpp) {
241 case 8:
242 val = LCD_LAYER_8BPP;
243 break;
244 case 16:
245 val = LCD_LAYER_16BPP;
246 break;
247 case 24:
248 val = LCD_LAYER_24BPP;
249 break;
250 case 32:
251 val = LCD_LAYER_32BPP;
252 break;
253 }
254
255 DRM_DEBUG("bpp=%d val=0x%x\n", bpp, val);
256 return val;
257}
258
259static void config_csc(struct kmb_drm_private *kmb, int plane_id)
260{
261 /* YUV to RGB conversion using the fixed matrix csc_coef_lcd */
262 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF11(plane_id), csc_coef_lcd[0]);
263 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF12(plane_id), csc_coef_lcd[1]);
264 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF13(plane_id), csc_coef_lcd[2]);
265 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF21(plane_id), csc_coef_lcd[3]);
266 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF22(plane_id), csc_coef_lcd[4]);
267 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF23(plane_id), csc_coef_lcd[5]);
268 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF31(plane_id), csc_coef_lcd[6]);
269 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF32(plane_id), csc_coef_lcd[7]);
270 kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF33(plane_id), csc_coef_lcd[8]);
271 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF1(plane_id), csc_coef_lcd[9]);
272 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF2(plane_id), csc_coef_lcd[10]);
273 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]);
274}
275
276static void kmb_plane_atomic_update(struct drm_plane *plane,
277 struct drm_plane_state *state)
278{
279 struct drm_framebuffer *fb;
280 struct kmb_drm_private *kmb;
281 unsigned int width;
282 unsigned int height;
283 unsigned int dma_len;
284 struct kmb_plane *kmb_plane;
285 unsigned int dma_cfg;
286 unsigned int ctrl = 0, val = 0, out_format = 0;
287 unsigned int src_w, src_h, crtc_x, crtc_y;
288 unsigned char plane_id;
289 int num_planes;
290 static dma_addr_t addr[MAX_SUB_PLANES];
291
292 if (!plane || !plane->state || !state)
293 return;
294
295 fb = plane->state->fb;
296 if (!fb)
297 return;
298 num_planes = fb->format->num_planes;
299 kmb_plane = to_kmb_plane(plane);
300 plane_id = kmb_plane->id;
301
302 kmb = to_kmb(plane->dev);
303
304 spin_lock_irq(&kmb->irq_lock);
305 if (kmb->kmb_under_flow || kmb->kmb_flush_done) {
306 spin_unlock_irq(&kmb->irq_lock);
307 drm_dbg(&kmb->drm, "plane_update:underflow!!!! returning");
308 return;
309 }
310 spin_unlock_irq(&kmb->irq_lock);
311
312 src_w = (plane->state->src_w >> 16);
313 src_h = plane->state->src_h >> 16;
314 crtc_x = plane->state->crtc_x;
315 crtc_y = plane->state->crtc_y;
316
317 drm_dbg(&kmb->drm,
318 "src_w=%d src_h=%d, fb->format->format=0x%x fb->flags=0x%x\n",
319 src_w, src_h, fb->format->format, fb->flags);
320
321 width = fb->width;
322 height = fb->height;
323 dma_len = (width * height * fb->format->cpp[0]);
324 drm_dbg(&kmb->drm, "dma_len=%d ", dma_len);
325 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN(plane_id), dma_len);
326 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN_SHADOW(plane_id), dma_len);
327 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
328 fb->pitches[0]);
329 kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),
330 (width * fb->format->cpp[0]));
331
332 addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, plane->state, 0);
333 kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id),
334 addr[Y_PLANE] + fb->offsets[0]);
335 val = get_pixel_format(fb->format->format);
336 val |= get_bits_per_pixel(fb->format);
337 /* Program Cb/Cr for planar formats */
338 if (num_planes > 1) {
339 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
340 width * fb->format->cpp[0]);
341 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
342 (width * fb->format->cpp[0]));
343
344 addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, plane->state,
345 U_PLANE);
346 /* check if Cb/Cr is swapped*/
347 if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER))
348 kmb_write_lcd(kmb,
349 LCD_LAYERn_DMA_START_CR_ADR(plane_id),
350 addr[U_PLANE]);
351 else
352 kmb_write_lcd(kmb,
353 LCD_LAYERn_DMA_START_CB_ADR(plane_id),
354 addr[U_PLANE]);
355
356 if (num_planes == 3) {
357 kmb_write_lcd(kmb,
358 LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
359 ((width) * fb->format->cpp[0]));
360
361 kmb_write_lcd(kmb,
362 LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
363 ((width) * fb->format->cpp[0]));
364
365 addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb,
366 plane->state,
367 V_PLANE);
368
369 /* check if Cb/Cr is swapped*/
370 if (val & LCD_LAYER_CRCB_ORDER)
371 kmb_write_lcd(kmb,
372 LCD_LAYERn_DMA_START_CB_ADR(plane_id),
373 addr[V_PLANE]);
374 else
375 kmb_write_lcd(kmb,
376 LCD_LAYERn_DMA_START_CR_ADR(plane_id),
377 addr[V_PLANE]);
378 }
379 }
380
381 kmb_write_lcd(kmb, LCD_LAYERn_WIDTH(plane_id), src_w - 1);
382 kmb_write_lcd(kmb, LCD_LAYERn_HEIGHT(plane_id), src_h - 1);
383 kmb_write_lcd(kmb, LCD_LAYERn_COL_START(plane_id), crtc_x);
384 kmb_write_lcd(kmb, LCD_LAYERn_ROW_START(plane_id), crtc_y);
385
386 val |= LCD_LAYER_FIFO_100;
387
388 if (val & LCD_LAYER_PLANAR_STORAGE) {
389 val |= LCD_LAYER_CSC_EN;
390
391 /* Enable CSC if input is planar and output is RGB */
392 config_csc(kmb, plane_id);
393 }
394
395 kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val);
396
397 switch (plane_id) {
398 case LAYER_0:
399 ctrl = LCD_CTRL_VL1_ENABLE;
400 break;
401 case LAYER_1:
402 ctrl = LCD_CTRL_VL2_ENABLE;
403 break;
404 case LAYER_2:
405 ctrl = LCD_CTRL_GL1_ENABLE;
406 break;
407 case LAYER_3:
408 ctrl = LCD_CTRL_GL2_ENABLE;
409 break;
410 }
411
412 ctrl |= LCD_CTRL_PROGRESSIVE | LCD_CTRL_TIM_GEN_ENABLE
413 | LCD_CTRL_CONTINUOUS | LCD_CTRL_OUTPUT_ENABLED;
414
415 /* LCD is connected to MIPI on kmb
416 * Therefore this bit is required for DSI Tx
417 */
418 ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;
419
420 kmb_set_bitmask_lcd(kmb, LCD_CONTROL, ctrl);
421
422 /* FIXME no doc on how to set output format,these values are
423 * taken from the Myriadx tests
424 */
425 out_format |= LCD_OUTF_FORMAT_RGB888;
426
427 /* Leave RGB order,conversion mode and clip mode to default */
428 /* do not interleave RGB channels for mipi Tx compatibility */
429 out_format |= LCD_OUTF_MIPI_RGB_MODE;
430 kmb_write_lcd(kmb, LCD_OUT_FORMAT_CFG, out_format);
431
432 dma_cfg = LCD_DMA_LAYER_ENABLE | LCD_DMA_LAYER_VSTRIDE_EN |
433 LCD_DMA_LAYER_CONT_UPDATE | LCD_DMA_LAYER_AXI_BURST_16;
434
435 /* Enable DMA */
436 kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
437 drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg,
438 kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id)));
439
440 kmb_set_bitmask_lcd(kmb, LCD_INT_CLEAR, LCD_INT_EOF |
441 LCD_INT_DMA_ERR);
442 kmb_set_bitmask_lcd(kmb, LCD_INT_ENABLE, LCD_INT_EOF |
443 LCD_INT_DMA_ERR);
444}
445
446static const struct drm_plane_helper_funcs kmb_plane_helper_funcs = {
447 .atomic_check = kmb_plane_atomic_check,
448 .atomic_update = kmb_plane_atomic_update,
449 .atomic_disable = kmb_plane_atomic_disable
450};
451
452void kmb_plane_destroy(struct drm_plane *plane)
453{
454 struct kmb_plane *kmb_plane = to_kmb_plane(plane);
455
456 drm_plane_cleanup(plane);
457 kfree(kmb_plane);
458}
459
460static const struct drm_plane_funcs kmb_plane_funcs = {
461 .update_plane = drm_atomic_helper_update_plane,
462 .disable_plane = drm_atomic_helper_disable_plane,
463 .destroy = kmb_plane_destroy,
464 .reset = drm_atomic_helper_plane_reset,
465 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
466 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
467};
468
469struct kmb_plane *kmb_plane_init(struct drm_device *drm)
470{
471 struct kmb_drm_private *kmb = to_kmb(drm);
472 struct kmb_plane *plane = NULL;
473 struct kmb_plane *primary = NULL;
474 int i = 0;
475 int ret = 0;
476 enum drm_plane_type plane_type;
477 const u32 *plane_formats;
478 int num_plane_formats;
479
480 for (i = 0; i < KMB_MAX_PLANES; i++) {
481 plane = drmm_kzalloc(drm, sizeof(*plane), GFP_KERNEL);
482
483 if (!plane) {
484 drm_err(drm, "Failed to allocate plane\n");
485 return ERR_PTR(-ENOMEM);
486 }
487
488 plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
489 DRM_PLANE_TYPE_OVERLAY;
490 if (i < 2) {
491 plane_formats = kmb_formats_v;
492 num_plane_formats = ARRAY_SIZE(kmb_formats_v);
493 } else {
494 plane_formats = kmb_formats_g;
495 num_plane_formats = ARRAY_SIZE(kmb_formats_g);
496 }
497
498 ret = drm_universal_plane_init(drm, &plane->base_plane,
499 POSSIBLE_CRTCS, &kmb_plane_funcs,
500 plane_formats, num_plane_formats,
501 NULL, plane_type, "plane %d", i);
502 if (ret < 0) {
503 drm_err(drm, "drm_universal_plane_init failed (ret=%d)",
504 ret);
505 goto cleanup;
506 }
507 drm_dbg(drm, "%s : %d i=%d type=%d",
508 __func__, __LINE__,
509 i, plane_type);
510 drm_plane_helper_add(&plane->base_plane,
511 &kmb_plane_helper_funcs);
512 if (plane_type == DRM_PLANE_TYPE_PRIMARY) {
513 primary = plane;
514 kmb->plane = plane;
515 }
516 drm_dbg(drm, "%s : %d primary=%p\n", __func__, __LINE__,
517 &primary->base_plane);
518 plane->id = i;
519 }
520
521 return primary;
522cleanup:
523 drmm_kfree(drm, plane);
524 return ERR_PTR(ret);
525}