brintos

brintos / linux-shallow public Read only

0
0
Text · 17.9 KiB · 9e0562a Raw
642 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright © 2018-2020 Intel Corporation4 */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_GL125};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, -22633};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(plane->dev);76	init_disp_cfg = kmb->init_disp_cfg[plane_id];77	/* Due to HW limitations, changing pixel format after initial78	 * 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(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, 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 after122	 * 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						   new_plane_state->crtc);134	return drm_atomic_helper_check_plane_state(new_plane_state,135						   crtc_state,136						   DRM_PLANE_NO_SCALING,137						   DRM_PLANE_NO_SCALING,138						   can_position, 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(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_STORAGE176		    | 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_STORAGE183		    | 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_STORAGE190		    | 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_STORAGE197		    | 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(kmb, LCD_LAYERn_CSC_COEFF11(plane_id), csc_coef_lcd[0]);290	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF12(plane_id), csc_coef_lcd[1]);291	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF13(plane_id), csc_coef_lcd[2]);292	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF21(plane_id), csc_coef_lcd[3]);293	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF22(plane_id), csc_coef_lcd[4]);294	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF23(plane_id), csc_coef_lcd[5]);295	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF31(plane_id), csc_coef_lcd[6]);296	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF32(plane_id), csc_coef_lcd[7]);297	kmb_write_lcd(kmb, LCD_LAYERn_CSC_COEFF33(plane_id), csc_coef_lcd[8]);298	kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF1(plane_id), csc_coef_lcd[9]);299	kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF2(plane_id), csc_coef_lcd[10]);300	kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF3(plane_id), 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(kmb, LCD_LAYERn_ALPHA(plane_id), 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(plane->dev);373	plane_id = kmb_plane->id;374 375	spin_lock_irq(&kmb->irq_lock);376	if (kmb->kmb_under_flow || kmb->kmb_flush_done) {377		spin_unlock_irq(&kmb->irq_lock);378		drm_dbg(&kmb->drm, "plane_update:underflow!!!! returning");379		return;380	}381	spin_unlock_irq(&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(kmb, LCD_LAYERn_DMA_LEN(plane_id), dma_len);398	kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN_SHADOW(plane_id), dma_len);399	kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),400		      fb->pitches[0]);401	kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),402		      (width * fb->format->cpp[0]));403 404	addr[Y_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0);405	kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id),406		      addr[Y_PLANE] + fb->offsets[0]);407	val = get_pixel_format(fb->format->format);408	val |= get_bits_per_pixel(fb->format);409	/* Program Cb/Cr for planar formats */410	if (num_planes > 1) {411		kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),412			      width * fb->format->cpp[0]);413		kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),414			      (width * fb->format->cpp[0]));415 416		addr[U_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state,417							U_PLANE);418		/* check if Cb/Cr is swapped*/419		if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER))420			kmb_write_lcd(kmb,421				      LCD_LAYERn_DMA_START_CR_ADR(plane_id),422					addr[U_PLANE]);423		else424			kmb_write_lcd(kmb,425				      LCD_LAYERn_DMA_START_CB_ADR(plane_id),426					addr[U_PLANE]);427 428		if (num_planes == 3) {429			kmb_write_lcd(kmb,430				      LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),431				      ((width) * fb->format->cpp[0]));432 433			kmb_write_lcd(kmb,434				      LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),435				      ((width) * fb->format->cpp[0]));436 437			addr[V_PLANE] = drm_fb_dma_get_gem_addr(fb,438								new_plane_state,439								V_PLANE);440 441			/* check if Cb/Cr is swapped*/442			if (val & LCD_LAYER_CRCB_ORDER)443				kmb_write_lcd(kmb,444					      LCD_LAYERn_DMA_START_CB_ADR(plane_id),445					      addr[V_PLANE]);446			else447				kmb_write_lcd(kmb,448					      LCD_LAYERn_DMA_START_CR_ADR(plane_id),449					      addr[V_PLANE]);450		}451	}452 453	kmb_write_lcd(kmb, LCD_LAYERn_WIDTH(plane_id), src_w - 1);454	kmb_write_lcd(kmb, LCD_LAYERn_HEIGHT(plane_id), src_h - 1);455	kmb_write_lcd(kmb, LCD_LAYERn_COL_START(plane_id), crtc_x);456	kmb_write_lcd(kmb, LCD_LAYERn_ROW_START(plane_id), 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, plane->state, plane_id, &val);468 469	kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val);470 471	/* Configure LCD_CONTROL */472	ctrl = kmb_read_lcd(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_ENABLE497	    | LCD_CTRL_CONTINUOUS | LCD_CTRL_OUTPUT_ENABLED;498 499	/* LCD is connected to MIPI on kmb500	 * Therefore this bit is required for DSI Tx501	 */502	ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;503 504	kmb_write_lcd(kmb, LCD_CONTROL, ctrl);505 506	/* Enable pipeline AXI read transactions for the DMA507	 * after setting graphics layers. This must be done508	 * in a separate write cycle.509	 */510	kmb_set_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);511 512	/* FIXME no doc on how to set output format, these values are taken513	 * from the Myriadx tests514	 */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(kmb, LCD_OUT_FORMAT_CFG, 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(kmb, LCD_LAYERn_DMA_CFG(plane_id), 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(kmb, LCD_INT_CLEAR, LCD_INT_EOF |541			LCD_INT_DMA_ERR);542	kmb_set_bitmask_lcd(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_disable550};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(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(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(drm, sizeof(*plane), GFP_KERNEL);585 586		if (!plane) {587			drm_err(drm, "Failed to allocate plane\n");588			return ERR_PTR(-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(drm, &plane->base_plane,602					       POSSIBLE_CRTCS, &kmb_plane_funcs,603					       plane_formats, num_plane_formats,604					       NULL, plane_type, "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->base_plane);614 615		drm_plane_create_blend_mode_property(&plane->base_plane,616						     blend_caps);617 618		drm_plane_create_zpos_immutable_property(&plane->base_plane, i);619 620		drm_plane_helper_add(&plane->base_plane,621				     &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 DMA633	 * prior to setting graphics layers634	 */635	kmb_clr_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);636 637	return primary;638cleanup:639	drmm_kfree(drm, plane);640	return ERR_PTR(ret);641}642