cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kmb_plane.c (18383B)


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