Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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	struct kmb_drm_private *kmb;
 71	struct kmb_plane *kmb_plane = to_kmb_plane(plane);
 72	int i;
 73	int plane_id = kmb_plane->id;
 74	struct disp_cfg init_disp_cfg;
 75
 76	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	}
 85	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,
 93				  struct drm_atomic_state *state)
 94{
 95	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
 96										 plane);
 97	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;
101	struct drm_framebuffer *fb;
102	int ret;
103	struct drm_crtc_state *crtc_state;
104	bool can_position;
105
106	kmb = to_kmb(plane->dev);
107	init_disp_cfg = kmb->init_disp_cfg[plane_id];
108	fb = new_plane_state->fb;
109	if (!fb || !new_plane_state->crtc)
110		return 0;
111
112	ret = check_pixel_format(plane, fb->format->format);
113	if (ret)
114		return ret;
115
116	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)
120		return -EINVAL;
121
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	}
131	can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
132	crtc_state =
133		drm_atomic_get_existing_crtc_state(state,
134						   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);
140}
141
142static void kmb_plane_atomic_disable(struct drm_plane *plane,
143				     struct drm_atomic_state *state)
144{
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
151	if (WARN_ON(plane_id >= KMB_MAX_PLANES))
152		return;
153
154	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
310static 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
348static void kmb_plane_atomic_update(struct drm_plane *plane,
349				    struct drm_atomic_state *state)
350{
351	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state,
352										 plane);
353	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
354										 plane);
355	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];
367	struct disp_cfg *init_disp_cfg;
368
369	if (!plane || !new_plane_state || !old_plane_state)
370		return;
371
372	fb = new_plane_state->fb;
373	if (!fb)
374		return;
375
376	num_planes = fb->format->num_planes;
377	kmb_plane = to_kmb_plane(plane);
378
379	kmb = to_kmb(plane->dev);
380	plane_id = kmb_plane->id;
381
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
390	init_disp_cfg = &kmb->init_disp_cfg[plane_id];
391	src_w = new_plane_state->src_w >> 16;
392	src_h = new_plane_state->src_h >> 16;
393	crtc_x = new_plane_state->crtc_x;
394	crtc_y = new_plane_state->crtc_y;
395
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
411	addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0);
412	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
423		addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state,
424							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,
445								new_plane_state,
446								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
474	kmb_plane_set_alpha(kmb, plane->state, plane_id, &val);
475
476	kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val);
477
478	/* 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
488	switch (plane_id) {
489	case LAYER_0:
490		ctrl |= LCD_CTRL_VL1_ENABLE;
491		break;
492	case LAYER_1:
493		ctrl |= LCD_CTRL_VL2_ENABLE;
494		break;
495	case LAYER_2:
496		ctrl |= LCD_CTRL_GL1_ENABLE;
497		break;
498	case LAYER_3:
499		ctrl |= LCD_CTRL_GL2_ENABLE;
500		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
511	kmb_write_lcd(kmb, LCD_CONTROL, ctrl);
512
513	/* 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
521	 */
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);
534
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
544	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;
586	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
587				  BIT(DRM_MODE_BLEND_PREMULTI)   |
588				  BIT(DRM_MODE_BLEND_COVERAGE);
589
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);
620		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
627		drm_plane_helper_add(&plane->base_plane,
628				     &kmb_plane_helper_funcs);
629
630		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
639	/* 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
644	return primary;
645cleanup:
646	drmm_kfree(drm, plane);
647	return ERR_PTR(ret);
648}