xref: /openbmc/linux/drivers/gpu/drm/arm/malidp_hw.c (revision 1b93d3cb)
1e559355aSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ad49f860SLiviu Dudau /*
3ad49f860SLiviu Dudau  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
4ad49f860SLiviu Dudau  * Author: Liviu Dudau <Liviu.Dudau@arm.com>
5ad49f860SLiviu Dudau  *
6ad49f860SLiviu Dudau  * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
7ad49f860SLiviu Dudau  * the difference between various versions of the hardware is being dealt with
8ad49f860SLiviu Dudau  * in an attempt to provide to the rest of the driver code a unified view
9ad49f860SLiviu Dudau  */
10ad49f860SLiviu Dudau 
11c2e7f82dSMihail Atanassov #include <linux/clk.h>
12535d1b94SSam Ravnborg #include <linux/delay.h>
13ad49f860SLiviu Dudau #include <linux/types.h>
14ad49f860SLiviu Dudau #include <linux/io.h>
15535d1b94SSam Ravnborg 
16ad49f860SLiviu Dudau #include <video/videomode.h>
17ad49f860SLiviu Dudau #include <video/display_timing.h>
18ad49f860SLiviu Dudau 
19535d1b94SSam Ravnborg #include <drm/drm_fourcc.h>
20535d1b94SSam Ravnborg #include <drm/drm_vblank.h>
21535d1b94SSam Ravnborg #include <drm/drm_print.h>
22535d1b94SSam Ravnborg 
23ad49f860SLiviu Dudau #include "malidp_drv.h"
24ad49f860SLiviu Dudau #include "malidp_hw.h"
258cbc5cafSBrian Starkey #include "malidp_mw.h"
26ad49f860SLiviu Dudau 
271cb3cbe7SLiviu Dudau enum {
281cb3cbe7SLiviu Dudau 	MW_NOT_ENABLED = 0,	/* SE writeback not enabled */
291cb3cbe7SLiviu Dudau 	MW_ONESHOT,		/* SE in one-shot mode for writeback */
301cb3cbe7SLiviu Dudau 	MW_START,		/* SE started writeback */
310735cfdfSLiviu Dudau 	MW_RESTART,		/* SE will start another writeback after this one */
320735cfdfSLiviu Dudau 	MW_STOP,		/* SE needs to stop after this writeback */
331cb3cbe7SLiviu Dudau };
341cb3cbe7SLiviu Dudau 
356211b486SBrian Starkey static const struct malidp_format_id malidp500_de_formats[] = {
36ad49f860SLiviu Dudau 	/*    fourcc,   layers supporting the format,     internal id  */
3709368e32SLiviu Dudau 	{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  0 },
3809368e32SLiviu Dudau 	{ DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  1 },
39ad49f860SLiviu Dudau 	{ DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  2 },
40ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  3 },
4109368e32SLiviu Dudau 	{ DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  4 },
4209368e32SLiviu Dudau 	{ DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  5 },
43ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  6 },
44ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  7 },
45ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  8 },
46ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  9 },
47ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
48ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
49ad49f860SLiviu Dudau 	{ DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
50ad49f860SLiviu Dudau 	{ DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
5109368e32SLiviu Dudau 	{ DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
52ad49f860SLiviu Dudau 	{ DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
53ed893860SAyan Kumar Halder 	{ DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
54ed893860SAyan Kumar Halder 	/* These are supported with AFBC only */
55ed893860SAyan Kumar Halder 	{ DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
56ed893860SAyan Kumar Halder 	{ DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
57ed893860SAyan Kumar Halder 	{ DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
58ed893860SAyan Kumar Halder 	{ DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
59ad49f860SLiviu Dudau };
60ad49f860SLiviu Dudau 
61ad49f860SLiviu Dudau #define MALIDP_ID(__group, __format) \
62ad49f860SLiviu Dudau 	((((__group) & 0x7) << 3) | ((__format) & 0x7))
63ad49f860SLiviu Dudau 
645e290226SAyan Kumar Halder #define AFBC_YUV_422_FORMAT_ID	MALIDP_ID(5, 1)
655e290226SAyan Kumar Halder 
66ad49f860SLiviu Dudau #define MALIDP_COMMON_FORMATS \
67ad49f860SLiviu Dudau 	/*    fourcc,   layers supporting the format,      internal id   */ \
68a67bbbe2SBrian Starkey 	{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
69a67bbbe2SBrian Starkey 	{ DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
70a67bbbe2SBrian Starkey 	{ DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
71a67bbbe2SBrian Starkey 	{ DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
72ad49f860SLiviu Dudau 	{ DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
73ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
74ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
75ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
76a67bbbe2SBrian Starkey 	{ DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
77a67bbbe2SBrian Starkey 	{ DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
78a67bbbe2SBrian Starkey 	{ DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
79a67bbbe2SBrian Starkey 	{ DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
80a67bbbe2SBrian Starkey 	{ DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
81a67bbbe2SBrian Starkey 	{ DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
82ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
83ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
84ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
85ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
86ed893860SAyan Kumar Halder 	/* This is only supported with linear modifier */	\
87ed893860SAyan Kumar Halder 	{ DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
88ed893860SAyan Kumar Halder 	/* This is only supported with AFBC modifier */		\
89ed893860SAyan Kumar Halder 	{ DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
90ad49f860SLiviu Dudau 	{ DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) },	\
91ed893860SAyan Kumar Halder 	/* This is only supported with linear modifier */ \
92ad49f860SLiviu Dudau 	{ DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) },	\
93a67bbbe2SBrian Starkey 	{ DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) },	\
94ed893860SAyan Kumar Halder 	/* This is only supported with AFBC modifier */ \
95ed893860SAyan Kumar Halder 	{ DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
9655bc277dSAlexandru Gheorghe 	{ DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
97ed893860SAyan Kumar Halder 	/* This is only supported with linear modifier */ \
98ed893860SAyan Kumar Halder 	{ DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
99ed893860SAyan Kumar Halder 	/* This is only supported with AFBC modifier */ \
100ed893860SAyan Kumar Halder 	{ DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
101ed893860SAyan Kumar Halder 	{ DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
102ed893860SAyan Kumar Halder 	/* This is only supported with AFBC modifier */ \
103ed893860SAyan Kumar Halder 	{ DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
104ed893860SAyan Kumar Halder 	{ DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
105ad49f860SLiviu Dudau 
1066211b486SBrian Starkey static const struct malidp_format_id malidp550_de_formats[] = {
107ad49f860SLiviu Dudau 	MALIDP_COMMON_FORMATS,
108ad49f860SLiviu Dudau };
109ad49f860SLiviu Dudau 
11055bc277dSAlexandru Gheorghe static const struct malidp_format_id malidp650_de_formats[] = {
11155bc277dSAlexandru Gheorghe 	MALIDP_COMMON_FORMATS,
11255bc277dSAlexandru Gheorghe 	{ DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)},
11355bc277dSAlexandru Gheorghe };
11455bc277dSAlexandru Gheorghe 
115ad49f860SLiviu Dudau static const struct malidp_layer malidp500_layers[] = {
1161f23a56aSJamie Fox 	/* id, base address, fb pointer address base, stride offset,
11766da13a5SLiviu Dudau 	 *	yuv2rgb matrix offset, mmu control register offset, rotation_features
1181f23a56aSJamie Fox 	 */
1191f23a56aSJamie Fox 	{ DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
12054b4260aSAyan Kumar Halder 		MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
12154b4260aSAyan Kumar Halder 		MALIDP500_DE_LV_AD_CTRL },
1221f23a56aSJamie Fox 	{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
12354b4260aSAyan Kumar Halder 		MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
12454b4260aSAyan Kumar Halder 		MALIDP500_DE_LG1_AD_CTRL },
1251f23a56aSJamie Fox 	{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
12654b4260aSAyan Kumar Halder 		MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
12754b4260aSAyan Kumar Halder 		MALIDP500_DE_LG2_AD_CTRL },
128ad49f860SLiviu Dudau };
129ad49f860SLiviu Dudau 
130ad49f860SLiviu Dudau static const struct malidp_layer malidp550_layers[] = {
1311f23a56aSJamie Fox 	/* id, base address, fb pointer address base, stride offset,
13266da13a5SLiviu Dudau 	 *	yuv2rgb matrix offset, mmu control register offset, rotation_features
1331f23a56aSJamie Fox 	 */
1341f23a56aSJamie Fox 	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
13554b4260aSAyan Kumar Halder 		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
13654b4260aSAyan Kumar Halder 		MALIDP550_DE_LV1_AD_CTRL },
1371f23a56aSJamie Fox 	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
13854b4260aSAyan Kumar Halder 		MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
13954b4260aSAyan Kumar Halder 		MALIDP550_DE_LG_AD_CTRL },
1401f23a56aSJamie Fox 	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
14154b4260aSAyan Kumar Halder 		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
14254b4260aSAyan Kumar Halder 		MALIDP550_DE_LV2_AD_CTRL },
1431f23a56aSJamie Fox 	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
14454b4260aSAyan Kumar Halder 		MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
1451f23a56aSJamie Fox };
1461f23a56aSJamie Fox 
1471f23a56aSJamie Fox static const struct malidp_layer malidp650_layers[] = {
1481f23a56aSJamie Fox 	/* id, base address, fb pointer address base, stride offset,
14966da13a5SLiviu Dudau 	 *	yuv2rgb matrix offset, mmu control register offset,
15066da13a5SLiviu Dudau 	 *	rotation_features
1511f23a56aSJamie Fox 	 */
1521f23a56aSJamie Fox 	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
1531f23a56aSJamie Fox 		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
15454b4260aSAyan Kumar Halder 		MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
15554b4260aSAyan Kumar Halder 		MALIDP550_DE_LV1_AD_CTRL },
1561f23a56aSJamie Fox 	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
15766da13a5SLiviu Dudau 		MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
15854b4260aSAyan Kumar Halder 		ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
1591f23a56aSJamie Fox 	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
1601f23a56aSJamie Fox 		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
16154b4260aSAyan Kumar Halder 		MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
16254b4260aSAyan Kumar Halder 		MALIDP550_DE_LV2_AD_CTRL },
1631f23a56aSJamie Fox 	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
16466da13a5SLiviu Dudau 		MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
16554b4260aSAyan Kumar Halder 		ROTATE_NONE, 0 },
166ad49f860SLiviu Dudau };
167ad49f860SLiviu Dudau 
1685e290226SAyan Kumar Halder const u64 malidp_format_modifiers[] = {
1695e290226SAyan Kumar Halder 	/* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
1705e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
1715e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
1725e290226SAyan Kumar Halder 
1735e290226SAyan Kumar Halder 	/* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
1745e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
1755e290226SAyan Kumar Halder 
1765e290226SAyan Kumar Halder 	/* All 8 or 10 bit YUV 444 formats. */
1775e290226SAyan Kumar Halder 	/* In DP550, 10 bit YUV 420 format also supported */
1785e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
1795e290226SAyan Kumar Halder 
1805e290226SAyan Kumar Halder 	/* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
1815e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
1825e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
1835e290226SAyan Kumar Halder 
1845e290226SAyan Kumar Halder 	/* YUV 420, 422 P1 8, 10 bit formats */
1855e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
1865e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
1875e290226SAyan Kumar Halder 
1885e290226SAyan Kumar Halder 	/* All formats */
1895e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_LINEAR,
1905e290226SAyan Kumar Halder 
1915e290226SAyan Kumar Halder 	DRM_FORMAT_MOD_INVALID
1925e290226SAyan Kumar Halder };
1935e290226SAyan Kumar Halder 
19428ce675bSMihail Atanassov #define SE_N_SCALING_COEFFS	96
19528ce675bSMihail Atanassov static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
19628ce675bSMihail Atanassov 	[MALIDP_UPSCALING_COEFFS - 1] = {
19728ce675bSMihail Atanassov 		0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
19828ce675bSMihail Atanassov 		0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
19928ce675bSMihail Atanassov 		0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
20028ce675bSMihail Atanassov 		0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
20128ce675bSMihail Atanassov 		0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
20228ce675bSMihail Atanassov 		0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
20328ce675bSMihail Atanassov 		0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
20428ce675bSMihail Atanassov 		0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
20528ce675bSMihail Atanassov 		0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
20628ce675bSMihail Atanassov 		0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
20728ce675bSMihail Atanassov 		0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
20828ce675bSMihail Atanassov 		0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
20928ce675bSMihail Atanassov 	},
21028ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
21128ce675bSMihail Atanassov 		0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
21228ce675bSMihail Atanassov 		0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
21328ce675bSMihail Atanassov 		0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
21428ce675bSMihail Atanassov 		0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
21528ce675bSMihail Atanassov 		0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
21628ce675bSMihail Atanassov 		0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
21728ce675bSMihail Atanassov 		0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
21828ce675bSMihail Atanassov 		0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
21928ce675bSMihail Atanassov 		0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
22028ce675bSMihail Atanassov 		0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
22128ce675bSMihail Atanassov 		0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
22228ce675bSMihail Atanassov 		0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
22328ce675bSMihail Atanassov 	},
22428ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_2_COEFFS - 1] = {
22528ce675bSMihail Atanassov 		0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
22628ce675bSMihail Atanassov 		0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
22728ce675bSMihail Atanassov 		0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
22828ce675bSMihail Atanassov 		0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
22928ce675bSMihail Atanassov 		0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
23028ce675bSMihail Atanassov 		0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
23128ce675bSMihail Atanassov 		0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
23228ce675bSMihail Atanassov 		0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
23328ce675bSMihail Atanassov 		0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
23428ce675bSMihail Atanassov 		0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
23528ce675bSMihail Atanassov 		0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
23628ce675bSMihail Atanassov 		0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
23728ce675bSMihail Atanassov 	},
23828ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
23928ce675bSMihail Atanassov 		0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
24028ce675bSMihail Atanassov 		0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
24128ce675bSMihail Atanassov 		0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
24228ce675bSMihail Atanassov 		0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
24328ce675bSMihail Atanassov 		0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
24428ce675bSMihail Atanassov 		0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
24528ce675bSMihail Atanassov 		0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
24628ce675bSMihail Atanassov 		0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
24728ce675bSMihail Atanassov 		0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
24828ce675bSMihail Atanassov 		0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
24928ce675bSMihail Atanassov 		0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
25028ce675bSMihail Atanassov 		0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
25128ce675bSMihail Atanassov 	},
25228ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_4_COEFFS - 1] = {
25328ce675bSMihail Atanassov 		0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
25428ce675bSMihail Atanassov 		0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
25528ce675bSMihail Atanassov 		0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
25628ce675bSMihail Atanassov 		0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
25728ce675bSMihail Atanassov 		0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
25828ce675bSMihail Atanassov 		0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
25928ce675bSMihail Atanassov 		0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
26028ce675bSMihail Atanassov 		0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
26128ce675bSMihail Atanassov 		0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
26228ce675bSMihail Atanassov 		0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
26328ce675bSMihail Atanassov 		0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
26428ce675bSMihail Atanassov 		0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
26528ce675bSMihail Atanassov 	},
26628ce675bSMihail Atanassov };
26728ce675bSMihail Atanassov 
268ad49f860SLiviu Dudau #define MALIDP_DE_DEFAULT_PREFETCH_START	5
269ad49f860SLiviu Dudau 
malidp500_query_hw(struct malidp_hw_device * hwdev)270ad49f860SLiviu Dudau static int malidp500_query_hw(struct malidp_hw_device *hwdev)
271ad49f860SLiviu Dudau {
272ad49f860SLiviu Dudau 	u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
273ad49f860SLiviu Dudau 	/* bit 4 of the CONFIG_ID register holds the line size multiplier */
274ad49f860SLiviu Dudau 	u8 ln_size_mult = conf & 0x10 ? 2 : 1;
275ad49f860SLiviu Dudau 
276ad49f860SLiviu Dudau 	hwdev->min_line_size = 2;
277ad49f860SLiviu Dudau 	hwdev->max_line_size = SZ_2K * ln_size_mult;
278ad49f860SLiviu Dudau 	hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
279ad49f860SLiviu Dudau 	hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
280ad49f860SLiviu Dudau 
281ad49f860SLiviu Dudau 	return 0;
282ad49f860SLiviu Dudau }
283ad49f860SLiviu Dudau 
malidp500_enter_config_mode(struct malidp_hw_device * hwdev)284ad49f860SLiviu Dudau static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
285ad49f860SLiviu Dudau {
286ad49f860SLiviu Dudau 	u32 status, count = 100;
287ad49f860SLiviu Dudau 
288ad49f860SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
289ad49f860SLiviu Dudau 	while (count) {
290a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
291ad49f860SLiviu Dudau 		if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
292ad49f860SLiviu Dudau 			break;
293ad49f860SLiviu Dudau 		/*
294ad49f860SLiviu Dudau 		 * entering config mode can take as long as the rendering
295ad49f860SLiviu Dudau 		 * of a full frame, hence the long sleep here
296ad49f860SLiviu Dudau 		 */
297ad49f860SLiviu Dudau 		usleep_range(1000, 10000);
298ad49f860SLiviu Dudau 		count--;
299ad49f860SLiviu Dudau 	}
300ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while entering config mode");
301ad49f860SLiviu Dudau }
302ad49f860SLiviu Dudau 
malidp500_leave_config_mode(struct malidp_hw_device * hwdev)303ad49f860SLiviu Dudau static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
304ad49f860SLiviu Dudau {
305ad49f860SLiviu Dudau 	u32 status, count = 100;
306ad49f860SLiviu Dudau 
307e64053f0SBrian Starkey 	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
308ad49f860SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
309ad49f860SLiviu Dudau 	while (count) {
310a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
311ad49f860SLiviu Dudau 		if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
312ad49f860SLiviu Dudau 			break;
313ad49f860SLiviu Dudau 		usleep_range(100, 1000);
314ad49f860SLiviu Dudau 		count--;
315ad49f860SLiviu Dudau 	}
316ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while leaving config mode");
317ad49f860SLiviu Dudau }
318ad49f860SLiviu Dudau 
malidp500_in_config_mode(struct malidp_hw_device * hwdev)319ad49f860SLiviu Dudau static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
320ad49f860SLiviu Dudau {
321ad49f860SLiviu Dudau 	u32 status;
322ad49f860SLiviu Dudau 
323a6993b21SLiviu Dudau 	status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
324ad49f860SLiviu Dudau 	if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
325ad49f860SLiviu Dudau 		return true;
326ad49f860SLiviu Dudau 
327ad49f860SLiviu Dudau 	return false;
328ad49f860SLiviu Dudau }
329ad49f860SLiviu Dudau 
malidp500_set_config_valid(struct malidp_hw_device * hwdev,u8 value)3300735cfdfSLiviu Dudau static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
331ad49f860SLiviu Dudau {
3320735cfdfSLiviu Dudau 	if (value)
333ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
3340735cfdfSLiviu Dudau 	else
3350735cfdfSLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
336ad49f860SLiviu Dudau }
337ad49f860SLiviu Dudau 
malidp500_modeset(struct malidp_hw_device * hwdev,struct videomode * mode)338ad49f860SLiviu Dudau static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
339ad49f860SLiviu Dudau {
340ad49f860SLiviu Dudau 	u32 val = 0;
341ad49f860SLiviu Dudau 
342f877006dSAyan Kumar Halder 	malidp_hw_write(hwdev, hwdev->output_color_depth,
343f877006dSAyan Kumar Halder 		hwdev->hw->map.out_depth_base);
344ad49f860SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
345ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
346ad49f860SLiviu Dudau 		val |= MALIDP500_HSYNCPOL;
347ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
348ad49f860SLiviu Dudau 		val |= MALIDP500_VSYNCPOL;
349ad49f860SLiviu Dudau 	val |= MALIDP_DE_DEFAULT_PREFETCH_START;
350ad49f860SLiviu Dudau 	malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
351ad49f860SLiviu Dudau 
352ad49f860SLiviu Dudau 	/*
353ad49f860SLiviu Dudau 	 * Mali-DP500 encodes the background color like this:
354ad49f860SLiviu Dudau 	 *    - red   @ MALIDP500_BGND_COLOR[12:0]
355ad49f860SLiviu Dudau 	 *    - green @ MALIDP500_BGND_COLOR[27:16]
356ad49f860SLiviu Dudau 	 *    - blue  @ (MALIDP500_BGND_COLOR + 4)[12:0]
357ad49f860SLiviu Dudau 	 */
358ad49f860SLiviu Dudau 	val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
359ad49f860SLiviu Dudau 	      (MALIDP_BGND_COLOR_R & 0xfff);
360ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
361ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
362ad49f860SLiviu Dudau 
363ad49f860SLiviu Dudau 	val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
364ad49f860SLiviu Dudau 		MALIDP_DE_H_BACKPORCH(mode->hback_porch);
365ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
366ad49f860SLiviu Dudau 
367ad49f860SLiviu Dudau 	val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
368ad49f860SLiviu Dudau 		MALIDP_DE_V_BACKPORCH(mode->vback_porch);
369ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
370ad49f860SLiviu Dudau 
371ad49f860SLiviu Dudau 	val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
372ad49f860SLiviu Dudau 		MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
373ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
374ad49f860SLiviu Dudau 
375ad49f860SLiviu Dudau 	val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
376ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
377ad49f860SLiviu Dudau 
378ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
379ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
380ad49f860SLiviu Dudau 	else
381ad49f860SLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
382d298e6a2SWen He 
383d298e6a2SWen He 	/*
384d298e6a2SWen He 	 * Program the RQoS register to avoid high resolutions flicker
385d298e6a2SWen He 	 * issue on the LS1028A.
386d298e6a2SWen He 	 */
387d298e6a2SWen He 	if (hwdev->arqos_value) {
388d298e6a2SWen He 		val = hwdev->arqos_value;
389d298e6a2SWen He 		malidp_hw_setbits(hwdev, val, MALIDP500_RQOS_QUALITY);
390d298e6a2SWen He 	}
391ad49f860SLiviu Dudau }
392ad49f860SLiviu Dudau 
malidp_format_get_bpp(u32 fmt)393b8207562SAyan Kumar Halder int malidp_format_get_bpp(u32 fmt)
394b8207562SAyan Kumar Halder {
39524c478eaSMaxime Ripard 	const struct drm_format_info *info = drm_format_info(fmt);
396b0f986b4SMaxime Ripard 	int bpp = info->cpp[0] * 8;
397b8207562SAyan Kumar Halder 
398b8207562SAyan Kumar Halder 	if (bpp == 0) {
399b8207562SAyan Kumar Halder 		switch (fmt) {
400b8207562SAyan Kumar Halder 		case DRM_FORMAT_VUY101010:
401b8207562SAyan Kumar Halder 			bpp = 30;
40228ba1b1dSAnders Roxell 			break;
403b8207562SAyan Kumar Halder 		case DRM_FORMAT_YUV420_10BIT:
404b8207562SAyan Kumar Halder 			bpp = 15;
405b8207562SAyan Kumar Halder 			break;
406b8207562SAyan Kumar Halder 		case DRM_FORMAT_YUV420_8BIT:
407b8207562SAyan Kumar Halder 			bpp = 12;
408b8207562SAyan Kumar Halder 			break;
409b8207562SAyan Kumar Halder 		default:
410b8207562SAyan Kumar Halder 			bpp = 0;
411b8207562SAyan Kumar Halder 		}
412b8207562SAyan Kumar Halder 	}
413b8207562SAyan Kumar Halder 
414b8207562SAyan Kumar Halder 	return bpp;
415b8207562SAyan Kumar Halder }
416b8207562SAyan Kumar Halder 
malidp500_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt,bool has_modifier)417b8207562SAyan Kumar Halder static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
418b8207562SAyan Kumar Halder 				     u16 h, u32 fmt, bool has_modifier)
419ad49f860SLiviu Dudau {
420ad49f860SLiviu Dudau 	/*
421ad49f860SLiviu Dudau 	 * Each layer needs enough rotation memory to fit 8 lines
422ad49f860SLiviu Dudau 	 * worth of pixel data. Required size is then:
423ad49f860SLiviu Dudau 	 *    size = rotated_width * (bpp / 8) * 8;
424ad49f860SLiviu Dudau 	 */
425b8207562SAyan Kumar Halder 	int bpp = malidp_format_get_bpp(fmt);
426b8207562SAyan Kumar Halder 
427b8207562SAyan Kumar Halder 	return w * bpp;
428ad49f860SLiviu Dudau }
429ad49f860SLiviu Dudau 
malidp500_se_write_pp_coefftab(struct malidp_hw_device * hwdev,u32 direction,u16 addr,u8 coeffs_id)43028ce675bSMihail Atanassov static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
43128ce675bSMihail Atanassov 					   u32 direction,
43228ce675bSMihail Atanassov 					   u16 addr,
43328ce675bSMihail Atanassov 					   u8 coeffs_id)
43428ce675bSMihail Atanassov {
43528ce675bSMihail Atanassov 	int i;
43628ce675bSMihail Atanassov 	u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
43728ce675bSMihail Atanassov 
43828ce675bSMihail Atanassov 	malidp_hw_write(hwdev,
43928ce675bSMihail Atanassov 			direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
44028ce675bSMihail Atanassov 			scaling_control + MALIDP_SE_COEFFTAB_ADDR);
44128ce675bSMihail Atanassov 	for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
44228ce675bSMihail Atanassov 		malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
44328ce675bSMihail Atanassov 				dp500_se_scaling_coeffs[coeffs_id][i]),
44428ce675bSMihail Atanassov 				scaling_control + MALIDP_SE_COEFFTAB_DATA);
44528ce675bSMihail Atanassov }
44628ce675bSMihail Atanassov 
malidp500_se_set_scaling_coeffs(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct malidp_se_config * old_config)44728ce675bSMihail Atanassov static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
44828ce675bSMihail Atanassov 					   struct malidp_se_config *se_config,
44928ce675bSMihail Atanassov 					   struct malidp_se_config *old_config)
45028ce675bSMihail Atanassov {
45128ce675bSMihail Atanassov 	/* Get array indices into dp500_se_scaling_coeffs. */
45228ce675bSMihail Atanassov 	u8 h = (u8)se_config->hcoeff - 1;
45328ce675bSMihail Atanassov 	u8 v = (u8)se_config->vcoeff - 1;
45428ce675bSMihail Atanassov 
45528ce675bSMihail Atanassov 	if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
45628ce675bSMihail Atanassov 		    v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
45728ce675bSMihail Atanassov 		return -EINVAL;
45828ce675bSMihail Atanassov 
45928ce675bSMihail Atanassov 	if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
46028ce675bSMihail Atanassov 			 se_config->vcoeff != old_config->vcoeff)) {
46128ce675bSMihail Atanassov 		malidp500_se_write_pp_coefftab(hwdev,
46228ce675bSMihail Atanassov 					       (MALIDP_SE_V_COEFFTAB |
46328ce675bSMihail Atanassov 						MALIDP_SE_H_COEFFTAB),
46428ce675bSMihail Atanassov 					       0, v);
46528ce675bSMihail Atanassov 	} else {
46628ce675bSMihail Atanassov 		if (se_config->vcoeff != old_config->vcoeff)
46728ce675bSMihail Atanassov 			malidp500_se_write_pp_coefftab(hwdev,
46828ce675bSMihail Atanassov 						       MALIDP_SE_V_COEFFTAB,
46928ce675bSMihail Atanassov 						       0, v);
47028ce675bSMihail Atanassov 		if (se_config->hcoeff != old_config->hcoeff)
47128ce675bSMihail Atanassov 			malidp500_se_write_pp_coefftab(hwdev,
47228ce675bSMihail Atanassov 						       MALIDP_SE_H_COEFFTAB,
47328ce675bSMihail Atanassov 						       0, h);
47428ce675bSMihail Atanassov 	}
47528ce675bSMihail Atanassov 
47628ce675bSMihail Atanassov 	return 0;
47728ce675bSMihail Atanassov }
47828ce675bSMihail Atanassov 
malidp500_se_calc_mclk(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct videomode * vm)479c2e7f82dSMihail Atanassov static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
480c2e7f82dSMihail Atanassov 				   struct malidp_se_config *se_config,
481c2e7f82dSMihail Atanassov 				   struct videomode *vm)
482c2e7f82dSMihail Atanassov {
483c2e7f82dSMihail Atanassov 	unsigned long mclk;
484c2e7f82dSMihail Atanassov 	unsigned long pxlclk = vm->pixelclock; /* Hz */
485c2e7f82dSMihail Atanassov 	unsigned long htotal = vm->hactive + vm->hfront_porch +
486c2e7f82dSMihail Atanassov 			       vm->hback_porch + vm->hsync_len;
487c2e7f82dSMihail Atanassov 	unsigned long input_size = se_config->input_w * se_config->input_h;
488c2e7f82dSMihail Atanassov 	unsigned long a = 10;
489c2e7f82dSMihail Atanassov 	long ret;
490c2e7f82dSMihail Atanassov 
491c2e7f82dSMihail Atanassov 	/*
492c2e7f82dSMihail Atanassov 	 * mclk = max(a, 1.5) * pxlclk
493c2e7f82dSMihail Atanassov 	 *
494c2e7f82dSMihail Atanassov 	 * To avoid float calculaiton, using 15 instead of 1.5 and div by
495c2e7f82dSMihail Atanassov 	 * 10 to get mclk.
496c2e7f82dSMihail Atanassov 	 */
497c2e7f82dSMihail Atanassov 	if (se_config->scale_enable) {
498c2e7f82dSMihail Atanassov 		a = 15 * input_size / (htotal * se_config->output_h);
499c2e7f82dSMihail Atanassov 		if (a < 15)
500c2e7f82dSMihail Atanassov 			a = 15;
501c2e7f82dSMihail Atanassov 	}
502c2e7f82dSMihail Atanassov 	mclk = a * pxlclk / 10;
503c2e7f82dSMihail Atanassov 	ret = clk_get_rate(hwdev->mclk);
504c2e7f82dSMihail Atanassov 	if (ret < mclk) {
505c2e7f82dSMihail Atanassov 		DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
506c2e7f82dSMihail Atanassov 				 mclk / 1000);
507c2e7f82dSMihail Atanassov 		return -EINVAL;
508c2e7f82dSMihail Atanassov 	}
509c2e7f82dSMihail Atanassov 	return ret;
510c2e7f82dSMihail Atanassov }
511c2e7f82dSMihail Atanassov 
malidp500_enable_memwrite(struct malidp_hw_device * hwdev,dma_addr_t * addrs,s32 * pitches,int num_planes,u16 w,u16 h,u32 fmt_id,const s16 * rgb2yuv_coeffs)5121cb3cbe7SLiviu Dudau static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
5131cb3cbe7SLiviu Dudau 				     dma_addr_t *addrs, s32 *pitches,
514b1150781SAlexandru Gheorghe 				     int num_planes, u16 w, u16 h, u32 fmt_id,
515b1150781SAlexandru Gheorghe 				     const s16 *rgb2yuv_coeffs)
5161cb3cbe7SLiviu Dudau {
5171cb3cbe7SLiviu Dudau 	u32 base = MALIDP500_SE_MEMWRITE_BASE;
5181cb3cbe7SLiviu Dudau 	u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
5191cb3cbe7SLiviu Dudau 
5201cb3cbe7SLiviu Dudau 	/* enable the scaling engine block */
5211cb3cbe7SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
5221cb3cbe7SLiviu Dudau 
5230735cfdfSLiviu Dudau 	/* restart the writeback if already enabled */
5240735cfdfSLiviu Dudau 	if (hwdev->mw_state != MW_NOT_ENABLED)
5250735cfdfSLiviu Dudau 		hwdev->mw_state = MW_RESTART;
5260735cfdfSLiviu Dudau 	else
5271cb3cbe7SLiviu Dudau 		hwdev->mw_state = MW_START;
5281cb3cbe7SLiviu Dudau 
5291cb3cbe7SLiviu Dudau 	malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
5301cb3cbe7SLiviu Dudau 	switch (num_planes) {
5311cb3cbe7SLiviu Dudau 	case 2:
5321cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
5331cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
5341cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
535df561f66SGustavo A. R. Silva 		fallthrough;
5361cb3cbe7SLiviu Dudau 	case 1:
5371cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
5381cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
5391cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
5401cb3cbe7SLiviu Dudau 		break;
5411cb3cbe7SLiviu Dudau 	default:
5421cb3cbe7SLiviu Dudau 		WARN(1, "Invalid number of planes");
5431cb3cbe7SLiviu Dudau 	}
5441cb3cbe7SLiviu Dudau 
5451cb3cbe7SLiviu Dudau 	malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
5461cb3cbe7SLiviu Dudau 			MALIDP500_SE_MEMWRITE_OUT_SIZE);
547b1150781SAlexandru Gheorghe 
548b1150781SAlexandru Gheorghe 	if (rgb2yuv_coeffs) {
549b1150781SAlexandru Gheorghe 		int i;
550b1150781SAlexandru Gheorghe 
551b1150781SAlexandru Gheorghe 		for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
552b1150781SAlexandru Gheorghe 			malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
553b1150781SAlexandru Gheorghe 					MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
554b1150781SAlexandru Gheorghe 		}
555b1150781SAlexandru Gheorghe 	}
556b1150781SAlexandru Gheorghe 
5571cb3cbe7SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
5581cb3cbe7SLiviu Dudau 
5591cb3cbe7SLiviu Dudau 	return 0;
5601cb3cbe7SLiviu Dudau }
5611cb3cbe7SLiviu Dudau 
malidp500_disable_memwrite(struct malidp_hw_device * hwdev)5621cb3cbe7SLiviu Dudau static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
5631cb3cbe7SLiviu Dudau {
5641cb3cbe7SLiviu Dudau 	u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
5651cb3cbe7SLiviu Dudau 
5660735cfdfSLiviu Dudau 	if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
5671cb3cbe7SLiviu Dudau 		hwdev->mw_state = MW_STOP;
5681cb3cbe7SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
5691cb3cbe7SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
5701cb3cbe7SLiviu Dudau }
5711cb3cbe7SLiviu Dudau 
malidp550_query_hw(struct malidp_hw_device * hwdev)572ad49f860SLiviu Dudau static int malidp550_query_hw(struct malidp_hw_device *hwdev)
573ad49f860SLiviu Dudau {
574ad49f860SLiviu Dudau 	u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
575ad49f860SLiviu Dudau 	u8 ln_size = (conf >> 4) & 0x3, rsize;
576ad49f860SLiviu Dudau 
577ad49f860SLiviu Dudau 	hwdev->min_line_size = 2;
578ad49f860SLiviu Dudau 
579ad49f860SLiviu Dudau 	switch (ln_size) {
580ad49f860SLiviu Dudau 	case 0:
581ad49f860SLiviu Dudau 		hwdev->max_line_size = SZ_2K;
582ad49f860SLiviu Dudau 		/* two banks of 64KB for rotation memory */
583ad49f860SLiviu Dudau 		rsize = 64;
584ad49f860SLiviu Dudau 		break;
585ad49f860SLiviu Dudau 	case 1:
586ad49f860SLiviu Dudau 		hwdev->max_line_size = SZ_4K;
587ad49f860SLiviu Dudau 		/* two banks of 128KB for rotation memory */
588ad49f860SLiviu Dudau 		rsize = 128;
589ad49f860SLiviu Dudau 		break;
590ad49f860SLiviu Dudau 	case 2:
591ad49f860SLiviu Dudau 		hwdev->max_line_size = 1280;
592ad49f860SLiviu Dudau 		/* two banks of 40KB for rotation memory */
593ad49f860SLiviu Dudau 		rsize = 40;
594ad49f860SLiviu Dudau 		break;
595ad49f860SLiviu Dudau 	case 3:
596ad49f860SLiviu Dudau 		/* reserved value */
597ad49f860SLiviu Dudau 		hwdev->max_line_size = 0;
598ad49f860SLiviu Dudau 		return -EINVAL;
599ad49f860SLiviu Dudau 	}
600ad49f860SLiviu Dudau 
601ad49f860SLiviu Dudau 	hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
602ad49f860SLiviu Dudau 	return 0;
603ad49f860SLiviu Dudau }
604ad49f860SLiviu Dudau 
malidp550_enter_config_mode(struct malidp_hw_device * hwdev)605ad49f860SLiviu Dudau static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
606ad49f860SLiviu Dudau {
607ad49f860SLiviu Dudau 	u32 status, count = 100;
608ad49f860SLiviu Dudau 
609ad49f860SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
610ad49f860SLiviu Dudau 	while (count) {
611a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
612ad49f860SLiviu Dudau 		if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
613ad49f860SLiviu Dudau 			break;
614ad49f860SLiviu Dudau 		/*
615ad49f860SLiviu Dudau 		 * entering config mode can take as long as the rendering
616ad49f860SLiviu Dudau 		 * of a full frame, hence the long sleep here
617ad49f860SLiviu Dudau 		 */
618ad49f860SLiviu Dudau 		usleep_range(1000, 10000);
619ad49f860SLiviu Dudau 		count--;
620ad49f860SLiviu Dudau 	}
621ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while entering config mode");
622ad49f860SLiviu Dudau }
623ad49f860SLiviu Dudau 
malidp550_leave_config_mode(struct malidp_hw_device * hwdev)624ad49f860SLiviu Dudau static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
625ad49f860SLiviu Dudau {
626ad49f860SLiviu Dudau 	u32 status, count = 100;
627ad49f860SLiviu Dudau 
628e64053f0SBrian Starkey 	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
629ad49f860SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
630ad49f860SLiviu Dudau 	while (count) {
631a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
632ad49f860SLiviu Dudau 		if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
633ad49f860SLiviu Dudau 			break;
634ad49f860SLiviu Dudau 		usleep_range(100, 1000);
635ad49f860SLiviu Dudau 		count--;
636ad49f860SLiviu Dudau 	}
637ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while leaving config mode");
638ad49f860SLiviu Dudau }
639ad49f860SLiviu Dudau 
malidp550_in_config_mode(struct malidp_hw_device * hwdev)640ad49f860SLiviu Dudau static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
641ad49f860SLiviu Dudau {
642ad49f860SLiviu Dudau 	u32 status;
643ad49f860SLiviu Dudau 
644a6993b21SLiviu Dudau 	status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
645ad49f860SLiviu Dudau 	if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
646ad49f860SLiviu Dudau 		return true;
647ad49f860SLiviu Dudau 
648ad49f860SLiviu Dudau 	return false;
649ad49f860SLiviu Dudau }
650ad49f860SLiviu Dudau 
malidp550_set_config_valid(struct malidp_hw_device * hwdev,u8 value)6510735cfdfSLiviu Dudau static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
652ad49f860SLiviu Dudau {
6530735cfdfSLiviu Dudau 	if (value)
654ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
6550735cfdfSLiviu Dudau 	else
6560735cfdfSLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
657ad49f860SLiviu Dudau }
658ad49f860SLiviu Dudau 
malidp550_modeset(struct malidp_hw_device * hwdev,struct videomode * mode)659ad49f860SLiviu Dudau static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
660ad49f860SLiviu Dudau {
661ad49f860SLiviu Dudau 	u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
662ad49f860SLiviu Dudau 
663f877006dSAyan Kumar Halder 	malidp_hw_write(hwdev, hwdev->output_color_depth,
664f877006dSAyan Kumar Halder 		hwdev->hw->map.out_depth_base);
665ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
666ad49f860SLiviu Dudau 	/*
667ad49f860SLiviu Dudau 	 * Mali-DP550 and Mali-DP650 encode the background color like this:
668ad49f860SLiviu Dudau 	 *   - red   @ MALIDP550_DE_BGND_COLOR[23:16]
669ad49f860SLiviu Dudau 	 *   - green @ MALIDP550_DE_BGND_COLOR[15:8]
670ad49f860SLiviu Dudau 	 *   - blue  @ MALIDP550_DE_BGND_COLOR[7:0]
671ad49f860SLiviu Dudau 	 *
672ad49f860SLiviu Dudau 	 * We need to truncate the least significant 4 bits from the default
673ad49f860SLiviu Dudau 	 * MALIDP_BGND_COLOR_x values
674ad49f860SLiviu Dudau 	 */
675ad49f860SLiviu Dudau 	val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
676ad49f860SLiviu Dudau 	      (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
677ad49f860SLiviu Dudau 	      ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
678ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
679ad49f860SLiviu Dudau 
680ad49f860SLiviu Dudau 	val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
681ad49f860SLiviu Dudau 		MALIDP_DE_H_BACKPORCH(mode->hback_porch);
682ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
683ad49f860SLiviu Dudau 
684ad49f860SLiviu Dudau 	val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
685ad49f860SLiviu Dudau 		MALIDP_DE_V_BACKPORCH(mode->vback_porch);
686ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
687ad49f860SLiviu Dudau 
688ad49f860SLiviu Dudau 	val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
689ad49f860SLiviu Dudau 		MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
690ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
691ad49f860SLiviu Dudau 		val |= MALIDP550_HSYNCPOL;
692ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
693ad49f860SLiviu Dudau 		val |= MALIDP550_VSYNCPOL;
694ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
695ad49f860SLiviu Dudau 
696ad49f860SLiviu Dudau 	val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
697ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
698ad49f860SLiviu Dudau 
699ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
700ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
701ad49f860SLiviu Dudau 	else
702ad49f860SLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
703ad49f860SLiviu Dudau }
704ad49f860SLiviu Dudau 
malidpx50_get_bytes_per_column(u32 fmt)705b8207562SAyan Kumar Halder static int malidpx50_get_bytes_per_column(u32 fmt)
706ad49f860SLiviu Dudau {
707b8207562SAyan Kumar Halder 	u32 bytes_per_column;
708ad49f860SLiviu Dudau 
709ad49f860SLiviu Dudau 	switch (fmt) {
710ad49f860SLiviu Dudau 	/* 8 lines at 4 bytes per pixel */
711ad49f860SLiviu Dudau 	case DRM_FORMAT_ARGB2101010:
712ad49f860SLiviu Dudau 	case DRM_FORMAT_ABGR2101010:
713ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBA1010102:
714ad49f860SLiviu Dudau 	case DRM_FORMAT_BGRA1010102:
715ad49f860SLiviu Dudau 	case DRM_FORMAT_ARGB8888:
716ad49f860SLiviu Dudau 	case DRM_FORMAT_ABGR8888:
717ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBA8888:
718ad49f860SLiviu Dudau 	case DRM_FORMAT_BGRA8888:
719ad49f860SLiviu Dudau 	case DRM_FORMAT_XRGB8888:
720ad49f860SLiviu Dudau 	case DRM_FORMAT_XBGR8888:
721ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBX8888:
722ad49f860SLiviu Dudau 	case DRM_FORMAT_BGRX8888:
723ad49f860SLiviu Dudau 	case DRM_FORMAT_RGB888:
724ad49f860SLiviu Dudau 	case DRM_FORMAT_BGR888:
725ad49f860SLiviu Dudau 	/* 16 lines at 2 bytes per pixel */
726ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBA5551:
727ad49f860SLiviu Dudau 	case DRM_FORMAT_ABGR1555:
728ad49f860SLiviu Dudau 	case DRM_FORMAT_RGB565:
729ad49f860SLiviu Dudau 	case DRM_FORMAT_BGR565:
730ad49f860SLiviu Dudau 	case DRM_FORMAT_UYVY:
731ad49f860SLiviu Dudau 	case DRM_FORMAT_YUYV:
73255bc277dSAlexandru Gheorghe 	case DRM_FORMAT_X0L0:
733b8207562SAyan Kumar Halder 		bytes_per_column = 32;
734ad49f860SLiviu Dudau 		break;
735ad49f860SLiviu Dudau 	/* 16 lines at 1.5 bytes per pixel */
736ad49f860SLiviu Dudau 	case DRM_FORMAT_NV12:
737ad49f860SLiviu Dudau 	case DRM_FORMAT_YUV420:
738b8207562SAyan Kumar Halder 	/* 8 lines at 3 bytes per pixel */
739b8207562SAyan Kumar Halder 	case DRM_FORMAT_VUY888:
740b8207562SAyan Kumar Halder 	/* 16 lines at 12 bits per pixel */
741b8207562SAyan Kumar Halder 	case DRM_FORMAT_YUV420_8BIT:
742b8207562SAyan Kumar Halder 	/* 8 lines at 3 bytes per pixel */
743b8207562SAyan Kumar Halder 	case DRM_FORMAT_P010:
744b8207562SAyan Kumar Halder 		bytes_per_column = 24;
745b8207562SAyan Kumar Halder 		break;
746b8207562SAyan Kumar Halder 	/* 8 lines at 30 bits per pixel */
747b8207562SAyan Kumar Halder 	case DRM_FORMAT_VUY101010:
748b8207562SAyan Kumar Halder 	/* 16 lines at 15 bits per pixel */
749b8207562SAyan Kumar Halder 	case DRM_FORMAT_YUV420_10BIT:
750b8207562SAyan Kumar Halder 		bytes_per_column = 30;
751ad49f860SLiviu Dudau 		break;
752ad49f860SLiviu Dudau 	default:
753ad49f860SLiviu Dudau 		return -EINVAL;
754ad49f860SLiviu Dudau 	}
755ad49f860SLiviu Dudau 
756b8207562SAyan Kumar Halder 	return bytes_per_column;
757b8207562SAyan Kumar Halder }
758b8207562SAyan Kumar Halder 
malidp550_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt,bool has_modifier)759b8207562SAyan Kumar Halder static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
760b8207562SAyan Kumar Halder 				     u16 h, u32 fmt, bool has_modifier)
761b8207562SAyan Kumar Halder {
762b8207562SAyan Kumar Halder 	int bytes_per_column = 0;
763b8207562SAyan Kumar Halder 
764b8207562SAyan Kumar Halder 	switch (fmt) {
765b8207562SAyan Kumar Halder 	/* 8 lines at 15 bits per pixel */
766b8207562SAyan Kumar Halder 	case DRM_FORMAT_YUV420_10BIT:
767b8207562SAyan Kumar Halder 		bytes_per_column = 15;
768b8207562SAyan Kumar Halder 		break;
769b8207562SAyan Kumar Halder 	/* Uncompressed YUV 420 10 bit single plane cannot be rotated */
770b8207562SAyan Kumar Halder 	case DRM_FORMAT_X0L2:
771b8207562SAyan Kumar Halder 		if (has_modifier)
772b8207562SAyan Kumar Halder 			bytes_per_column = 8;
773b8207562SAyan Kumar Halder 		else
774b8207562SAyan Kumar Halder 			return -EINVAL;
775b8207562SAyan Kumar Halder 		break;
776b8207562SAyan Kumar Halder 	default:
777b8207562SAyan Kumar Halder 		bytes_per_column = malidpx50_get_bytes_per_column(fmt);
778b8207562SAyan Kumar Halder 	}
779b8207562SAyan Kumar Halder 
780b8207562SAyan Kumar Halder 	if (bytes_per_column == -EINVAL)
781b8207562SAyan Kumar Halder 		return bytes_per_column;
782b8207562SAyan Kumar Halder 
783b8207562SAyan Kumar Halder 	return w * bytes_per_column;
784b8207562SAyan Kumar Halder }
785b8207562SAyan Kumar Halder 
malidp650_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt,bool has_modifier)786b8207562SAyan Kumar Halder static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
787b8207562SAyan Kumar Halder 				     u16 h, u32 fmt, bool has_modifier)
788b8207562SAyan Kumar Halder {
789b8207562SAyan Kumar Halder 	int bytes_per_column = 0;
790b8207562SAyan Kumar Halder 
791b8207562SAyan Kumar Halder 	switch (fmt) {
792b8207562SAyan Kumar Halder 	/* 16 lines at 2 bytes per pixel */
793b8207562SAyan Kumar Halder 	case DRM_FORMAT_X0L2:
794b8207562SAyan Kumar Halder 		bytes_per_column = 32;
795b8207562SAyan Kumar Halder 		break;
796b8207562SAyan Kumar Halder 	default:
797b8207562SAyan Kumar Halder 		bytes_per_column = malidpx50_get_bytes_per_column(fmt);
798b8207562SAyan Kumar Halder 	}
799b8207562SAyan Kumar Halder 
800b8207562SAyan Kumar Halder 	if (bytes_per_column == -EINVAL)
801b8207562SAyan Kumar Halder 		return bytes_per_column;
802b8207562SAyan Kumar Halder 
803b8207562SAyan Kumar Halder 	return w * bytes_per_column;
804ad49f860SLiviu Dudau }
805ad49f860SLiviu Dudau 
malidp550_se_set_scaling_coeffs(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct malidp_se_config * old_config)80628ce675bSMihail Atanassov static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
80728ce675bSMihail Atanassov 					   struct malidp_se_config *se_config,
80828ce675bSMihail Atanassov 					   struct malidp_se_config *old_config)
80928ce675bSMihail Atanassov {
81028ce675bSMihail Atanassov 	u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
81128ce675bSMihail Atanassov 		   MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
81228ce675bSMihail Atanassov 	u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
81328ce675bSMihail Atanassov 			MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
81428ce675bSMihail Atanassov 
81528ce675bSMihail Atanassov 	malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
81628ce675bSMihail Atanassov 	malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
81728ce675bSMihail Atanassov 	return 0;
81828ce675bSMihail Atanassov }
81928ce675bSMihail Atanassov 
malidp550_se_calc_mclk(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct videomode * vm)820c2e7f82dSMihail Atanassov static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
821c2e7f82dSMihail Atanassov 				   struct malidp_se_config *se_config,
822c2e7f82dSMihail Atanassov 				   struct videomode *vm)
823c2e7f82dSMihail Atanassov {
824c2e7f82dSMihail Atanassov 	unsigned long mclk;
825c2e7f82dSMihail Atanassov 	unsigned long pxlclk = vm->pixelclock;
826c2e7f82dSMihail Atanassov 	unsigned long htotal = vm->hactive + vm->hfront_porch +
827c2e7f82dSMihail Atanassov 			       vm->hback_porch + vm->hsync_len;
828c2e7f82dSMihail Atanassov 	unsigned long numerator = 1, denominator = 1;
829c2e7f82dSMihail Atanassov 	long ret;
830c2e7f82dSMihail Atanassov 
831c2e7f82dSMihail Atanassov 	if (se_config->scale_enable) {
832c2e7f82dSMihail Atanassov 		numerator = max(se_config->input_w, se_config->output_w) *
833c2e7f82dSMihail Atanassov 			    se_config->input_h;
834c2e7f82dSMihail Atanassov 		numerator += se_config->output_w *
835c2e7f82dSMihail Atanassov 			     (se_config->output_h -
836c2e7f82dSMihail Atanassov 			      min(se_config->input_h, se_config->output_h));
837c2e7f82dSMihail Atanassov 		denominator = (htotal - 2) * se_config->output_h;
838c2e7f82dSMihail Atanassov 	}
839c2e7f82dSMihail Atanassov 
840c2e7f82dSMihail Atanassov 	/* mclk can't be slower than pxlclk. */
841c2e7f82dSMihail Atanassov 	if (numerator < denominator)
842c2e7f82dSMihail Atanassov 		numerator = denominator = 1;
843c2e7f82dSMihail Atanassov 	mclk = (pxlclk * numerator) / denominator;
844c2e7f82dSMihail Atanassov 	ret = clk_get_rate(hwdev->mclk);
845c2e7f82dSMihail Atanassov 	if (ret < mclk) {
846c2e7f82dSMihail Atanassov 		DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
847c2e7f82dSMihail Atanassov 				 mclk / 1000);
848c2e7f82dSMihail Atanassov 		return -EINVAL;
849c2e7f82dSMihail Atanassov 	}
850c2e7f82dSMihail Atanassov 	return ret;
851c2e7f82dSMihail Atanassov }
852c2e7f82dSMihail Atanassov 
malidp550_enable_memwrite(struct malidp_hw_device * hwdev,dma_addr_t * addrs,s32 * pitches,int num_planes,u16 w,u16 h,u32 fmt_id,const s16 * rgb2yuv_coeffs)853846c87a0SLiviu Dudau static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
854846c87a0SLiviu Dudau 				     dma_addr_t *addrs, s32 *pitches,
855b1150781SAlexandru Gheorghe 				     int num_planes, u16 w, u16 h, u32 fmt_id,
856b1150781SAlexandru Gheorghe 				     const s16 *rgb2yuv_coeffs)
857846c87a0SLiviu Dudau {
858846c87a0SLiviu Dudau 	u32 base = MALIDP550_SE_MEMWRITE_BASE;
859846c87a0SLiviu Dudau 	u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
860846c87a0SLiviu Dudau 
861846c87a0SLiviu Dudau 	/* enable the scaling engine block */
862846c87a0SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
863846c87a0SLiviu Dudau 
8641cb3cbe7SLiviu Dudau 	hwdev->mw_state = MW_ONESHOT;
8651cb3cbe7SLiviu Dudau 
866846c87a0SLiviu Dudau 	malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
867846c87a0SLiviu Dudau 	switch (num_planes) {
868846c87a0SLiviu Dudau 	case 2:
869846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
870846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
871846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
872df561f66SGustavo A. R. Silva 		fallthrough;
873846c87a0SLiviu Dudau 	case 1:
874846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
875846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
876846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
877846c87a0SLiviu Dudau 		break;
878846c87a0SLiviu Dudau 	default:
879846c87a0SLiviu Dudau 		WARN(1, "Invalid number of planes");
880846c87a0SLiviu Dudau 	}
881846c87a0SLiviu Dudau 
882846c87a0SLiviu Dudau 	malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
883846c87a0SLiviu Dudau 			MALIDP550_SE_MEMWRITE_OUT_SIZE);
884846c87a0SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
885846c87a0SLiviu Dudau 			  MALIDP550_SE_CONTROL);
886846c87a0SLiviu Dudau 
887b1150781SAlexandru Gheorghe 	if (rgb2yuv_coeffs) {
888b1150781SAlexandru Gheorghe 		int i;
889b1150781SAlexandru Gheorghe 
890b1150781SAlexandru Gheorghe 		for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
891b1150781SAlexandru Gheorghe 			malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
892b1150781SAlexandru Gheorghe 					MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
893b1150781SAlexandru Gheorghe 		}
894b1150781SAlexandru Gheorghe 	}
895b1150781SAlexandru Gheorghe 
896846c87a0SLiviu Dudau 	return 0;
897846c87a0SLiviu Dudau }
898846c87a0SLiviu Dudau 
malidp550_disable_memwrite(struct malidp_hw_device * hwdev)899846c87a0SLiviu Dudau static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
900846c87a0SLiviu Dudau {
901846c87a0SLiviu Dudau 	u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
902846c87a0SLiviu Dudau 
903846c87a0SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
904846c87a0SLiviu Dudau 			    MALIDP550_SE_CONTROL);
905846c87a0SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
906846c87a0SLiviu Dudau }
907846c87a0SLiviu Dudau 
malidp650_query_hw(struct malidp_hw_device * hwdev)908ad49f860SLiviu Dudau static int malidp650_query_hw(struct malidp_hw_device *hwdev)
909ad49f860SLiviu Dudau {
910ad49f860SLiviu Dudau 	u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
911ad49f860SLiviu Dudau 	u8 ln_size = (conf >> 4) & 0x3, rsize;
912ad49f860SLiviu Dudau 
913ad49f860SLiviu Dudau 	hwdev->min_line_size = 4;
914ad49f860SLiviu Dudau 
915ad49f860SLiviu Dudau 	switch (ln_size) {
916ad49f860SLiviu Dudau 	case 0:
917ad49f860SLiviu Dudau 	case 2:
918ad49f860SLiviu Dudau 		/* reserved values */
919ad49f860SLiviu Dudau 		hwdev->max_line_size = 0;
920ad49f860SLiviu Dudau 		return -EINVAL;
921ad49f860SLiviu Dudau 	case 1:
922ad49f860SLiviu Dudau 		hwdev->max_line_size = SZ_4K;
923ad49f860SLiviu Dudau 		/* two banks of 128KB for rotation memory */
924ad49f860SLiviu Dudau 		rsize = 128;
925ad49f860SLiviu Dudau 		break;
926ad49f860SLiviu Dudau 	case 3:
927ad49f860SLiviu Dudau 		hwdev->max_line_size = 2560;
928ad49f860SLiviu Dudau 		/* two banks of 80KB for rotation memory */
929ad49f860SLiviu Dudau 		rsize = 80;
930ad49f860SLiviu Dudau 	}
931ad49f860SLiviu Dudau 
932ad49f860SLiviu Dudau 	hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
933ad49f860SLiviu Dudau 	return 0;
934ad49f860SLiviu Dudau }
935ad49f860SLiviu Dudau 
936a6993b21SLiviu Dudau const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
937ad49f860SLiviu Dudau 	[MALIDP_500] = {
938ad49f860SLiviu Dudau 		.map = {
93902725d31SMihail Atanassov 			.coeffs_base = MALIDP500_COEFFS_BASE,
940ad49f860SLiviu Dudau 			.se_base = MALIDP500_SE_BASE,
941ad49f860SLiviu Dudau 			.dc_base = MALIDP500_DC_BASE,
942ad49f860SLiviu Dudau 			.out_depth_base = MALIDP500_OUTPUT_DEPTH,
943ad49f860SLiviu Dudau 			.features = 0,	/* no CLEARIRQ register */
944ad49f860SLiviu Dudau 			.n_layers = ARRAY_SIZE(malidp500_layers),
945ad49f860SLiviu Dudau 			.layers = malidp500_layers,
946ad49f860SLiviu Dudau 			.de_irq_map = {
947ad49f860SLiviu Dudau 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
948ad49f860SLiviu Dudau 					    MALIDP500_DE_IRQ_AXI_ERR |
949ad49f860SLiviu Dudau 					    MALIDP500_DE_IRQ_VSYNC |
950ad49f860SLiviu Dudau 					    MALIDP500_DE_IRQ_GLOBAL,
951ad49f860SLiviu Dudau 				.vsync_irq = MALIDP500_DE_IRQ_VSYNC,
952613c5c7fSAlexandru Gheorghe 				.err_mask = MALIDP_DE_IRQ_UNDERRUN |
953613c5c7fSAlexandru Gheorghe 					    MALIDP500_DE_IRQ_AXI_ERR |
954613c5c7fSAlexandru Gheorghe 					    MALIDP500_DE_IRQ_SATURATION,
955ad49f860SLiviu Dudau 			},
956ad49f860SLiviu Dudau 			.se_irq_map = {
95789610dc2SAlison Wang 				.irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
9581cb3cbe7SLiviu Dudau 					    MALIDP500_SE_IRQ_CONF_VALID |
95989610dc2SAlison Wang 					    MALIDP500_SE_IRQ_GLOBAL,
9601cb3cbe7SLiviu Dudau 				.vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
961613c5c7fSAlexandru Gheorghe 				.err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
962613c5c7fSAlexandru Gheorghe 					    MALIDP500_SE_IRQ_AXI_ERROR |
963613c5c7fSAlexandru Gheorghe 					    MALIDP500_SE_IRQ_OVERRUN,
964ad49f860SLiviu Dudau 			},
965ad49f860SLiviu Dudau 			.dc_irq_map = {
966ad49f860SLiviu Dudau 				.irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
967ad49f860SLiviu Dudau 				.vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
968ad49f860SLiviu Dudau 			},
9696211b486SBrian Starkey 			.pixel_formats = malidp500_de_formats,
9706211b486SBrian Starkey 			.n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
971a228062cSBrian Starkey 			.bus_align_bytes = 8,
972ad49f860SLiviu Dudau 		},
973ad49f860SLiviu Dudau 		.query_hw = malidp500_query_hw,
974ad49f860SLiviu Dudau 		.enter_config_mode = malidp500_enter_config_mode,
975ad49f860SLiviu Dudau 		.leave_config_mode = malidp500_leave_config_mode,
976ad49f860SLiviu Dudau 		.in_config_mode = malidp500_in_config_mode,
977ad49f860SLiviu Dudau 		.set_config_valid = malidp500_set_config_valid,
978ad49f860SLiviu Dudau 		.modeset = malidp500_modeset,
979ad49f860SLiviu Dudau 		.rotmem_required = malidp500_rotmem_required,
98028ce675bSMihail Atanassov 		.se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
981c2e7f82dSMihail Atanassov 		.se_calc_mclk = malidp500_se_calc_mclk,
9821cb3cbe7SLiviu Dudau 		.enable_memwrite = malidp500_enable_memwrite,
9831cb3cbe7SLiviu Dudau 		.disable_memwrite = malidp500_disable_memwrite,
98483d642eeSMihail Atanassov 		.features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
985ad49f860SLiviu Dudau 	},
986ad49f860SLiviu Dudau 	[MALIDP_550] = {
987ad49f860SLiviu Dudau 		.map = {
98802725d31SMihail Atanassov 			.coeffs_base = MALIDP550_COEFFS_BASE,
989ad49f860SLiviu Dudau 			.se_base = MALIDP550_SE_BASE,
990ad49f860SLiviu Dudau 			.dc_base = MALIDP550_DC_BASE,
991ad49f860SLiviu Dudau 			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
9925e290226SAyan Kumar Halder 			.features = MALIDP_REGMAP_HAS_CLEARIRQ |
9935e290226SAyan Kumar Halder 				    MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
9945e290226SAyan Kumar Halder 				    MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
9955e290226SAyan Kumar Halder 				    MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
996ad49f860SLiviu Dudau 			.n_layers = ARRAY_SIZE(malidp550_layers),
997ad49f860SLiviu Dudau 			.layers = malidp550_layers,
998ad49f860SLiviu Dudau 			.de_irq_map = {
999ad49f860SLiviu Dudau 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1000ad49f860SLiviu Dudau 					    MALIDP550_DE_IRQ_VSYNC,
1001ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1002613c5c7fSAlexandru Gheorghe 				.err_mask = MALIDP_DE_IRQ_UNDERRUN |
1003613c5c7fSAlexandru Gheorghe 					    MALIDP550_DE_IRQ_SATURATION |
1004613c5c7fSAlexandru Gheorghe 					    MALIDP550_DE_IRQ_AXI_ERR,
1005ad49f860SLiviu Dudau 			},
1006ad49f860SLiviu Dudau 			.se_irq_map = {
1007613c5c7fSAlexandru Gheorghe 				.irq_mask = MALIDP550_SE_IRQ_EOW,
1008846c87a0SLiviu Dudau 				.vsync_irq = MALIDP550_SE_IRQ_EOW,
1009613c5c7fSAlexandru Gheorghe 				.err_mask  = MALIDP550_SE_IRQ_AXI_ERR |
1010613c5c7fSAlexandru Gheorghe 					     MALIDP550_SE_IRQ_OVR |
1011613c5c7fSAlexandru Gheorghe 					     MALIDP550_SE_IRQ_IBSY,
1012ad49f860SLiviu Dudau 			},
1013ad49f860SLiviu Dudau 			.dc_irq_map = {
1014846c87a0SLiviu Dudau 				.irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1015846c87a0SLiviu Dudau 					    MALIDP550_DC_IRQ_SE,
1016ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1017ad49f860SLiviu Dudau 			},
10186211b486SBrian Starkey 			.pixel_formats = malidp550_de_formats,
10196211b486SBrian Starkey 			.n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1020a228062cSBrian Starkey 			.bus_align_bytes = 8,
1021ad49f860SLiviu Dudau 		},
1022ad49f860SLiviu Dudau 		.query_hw = malidp550_query_hw,
1023ad49f860SLiviu Dudau 		.enter_config_mode = malidp550_enter_config_mode,
1024ad49f860SLiviu Dudau 		.leave_config_mode = malidp550_leave_config_mode,
1025ad49f860SLiviu Dudau 		.in_config_mode = malidp550_in_config_mode,
1026ad49f860SLiviu Dudau 		.set_config_valid = malidp550_set_config_valid,
1027ad49f860SLiviu Dudau 		.modeset = malidp550_modeset,
1028ad49f860SLiviu Dudau 		.rotmem_required = malidp550_rotmem_required,
102928ce675bSMihail Atanassov 		.se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1030c2e7f82dSMihail Atanassov 		.se_calc_mclk = malidp550_se_calc_mclk,
1031846c87a0SLiviu Dudau 		.enable_memwrite = malidp550_enable_memwrite,
1032846c87a0SLiviu Dudau 		.disable_memwrite = malidp550_disable_memwrite,
103383d642eeSMihail Atanassov 		.features = 0,
1034ad49f860SLiviu Dudau 	},
1035ad49f860SLiviu Dudau 	[MALIDP_650] = {
1036ad49f860SLiviu Dudau 		.map = {
103702725d31SMihail Atanassov 			.coeffs_base = MALIDP550_COEFFS_BASE,
1038ad49f860SLiviu Dudau 			.se_base = MALIDP550_SE_BASE,
1039ad49f860SLiviu Dudau 			.dc_base = MALIDP550_DC_BASE,
1040ad49f860SLiviu Dudau 			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
10415e290226SAyan Kumar Halder 			.features = MALIDP_REGMAP_HAS_CLEARIRQ |
10425e290226SAyan Kumar Halder 				    MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
10435e290226SAyan Kumar Halder 				    MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
10441f23a56aSJamie Fox 			.n_layers = ARRAY_SIZE(malidp650_layers),
10451f23a56aSJamie Fox 			.layers = malidp650_layers,
1046ad49f860SLiviu Dudau 			.de_irq_map = {
1047ad49f860SLiviu Dudau 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1048ad49f860SLiviu Dudau 					    MALIDP650_DE_IRQ_DRIFT |
1049ad49f860SLiviu Dudau 					    MALIDP550_DE_IRQ_VSYNC,
1050ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1051613c5c7fSAlexandru Gheorghe 				.err_mask = MALIDP_DE_IRQ_UNDERRUN |
1052613c5c7fSAlexandru Gheorghe 					    MALIDP650_DE_IRQ_DRIFT |
1053613c5c7fSAlexandru Gheorghe 					    MALIDP550_DE_IRQ_SATURATION |
1054613c5c7fSAlexandru Gheorghe 					    MALIDP550_DE_IRQ_AXI_ERR |
1055613c5c7fSAlexandru Gheorghe 					    MALIDP650_DE_IRQ_ACEV1 |
1056613c5c7fSAlexandru Gheorghe 					    MALIDP650_DE_IRQ_ACEV2 |
1057613c5c7fSAlexandru Gheorghe 					    MALIDP650_DE_IRQ_ACEG |
1058613c5c7fSAlexandru Gheorghe 					    MALIDP650_DE_IRQ_AXIEP,
1059ad49f860SLiviu Dudau 			},
1060ad49f860SLiviu Dudau 			.se_irq_map = {
1061613c5c7fSAlexandru Gheorghe 				.irq_mask = MALIDP550_SE_IRQ_EOW,
1062846c87a0SLiviu Dudau 				.vsync_irq = MALIDP550_SE_IRQ_EOW,
1063613c5c7fSAlexandru Gheorghe 				.err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1064613c5c7fSAlexandru Gheorghe 					    MALIDP550_SE_IRQ_OVR |
1065613c5c7fSAlexandru Gheorghe 					    MALIDP550_SE_IRQ_IBSY,
1066ad49f860SLiviu Dudau 			},
1067ad49f860SLiviu Dudau 			.dc_irq_map = {
1068846c87a0SLiviu Dudau 				.irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1069846c87a0SLiviu Dudau 					    MALIDP550_DC_IRQ_SE,
1070ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1071ad49f860SLiviu Dudau 			},
107255bc277dSAlexandru Gheorghe 			.pixel_formats = malidp650_de_formats,
107355bc277dSAlexandru Gheorghe 			.n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1074a228062cSBrian Starkey 			.bus_align_bytes = 16,
1075ad49f860SLiviu Dudau 		},
1076ad49f860SLiviu Dudau 		.query_hw = malidp650_query_hw,
1077ad49f860SLiviu Dudau 		.enter_config_mode = malidp550_enter_config_mode,
1078ad49f860SLiviu Dudau 		.leave_config_mode = malidp550_leave_config_mode,
1079ad49f860SLiviu Dudau 		.in_config_mode = malidp550_in_config_mode,
1080ad49f860SLiviu Dudau 		.set_config_valid = malidp550_set_config_valid,
1081ad49f860SLiviu Dudau 		.modeset = malidp550_modeset,
1082b8207562SAyan Kumar Halder 		.rotmem_required = malidp650_rotmem_required,
108328ce675bSMihail Atanassov 		.se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1084c2e7f82dSMihail Atanassov 		.se_calc_mclk = malidp550_se_calc_mclk,
1085846c87a0SLiviu Dudau 		.enable_memwrite = malidp550_enable_memwrite,
1086846c87a0SLiviu Dudau 		.disable_memwrite = malidp550_disable_memwrite,
108783d642eeSMihail Atanassov 		.features = 0,
1088ad49f860SLiviu Dudau 	},
1089ad49f860SLiviu Dudau };
1090ad49f860SLiviu Dudau 
malidp_hw_get_format_id(const struct malidp_hw_regmap * map,u8 layer_id,u32 format,bool has_modifier)1091ad49f860SLiviu Dudau u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
10925e290226SAyan Kumar Halder 			   u8 layer_id, u32 format, bool has_modifier)
1093ad49f860SLiviu Dudau {
1094ad49f860SLiviu Dudau 	unsigned int i;
1095ad49f860SLiviu Dudau 
10966211b486SBrian Starkey 	for (i = 0; i < map->n_pixel_formats; i++) {
10976211b486SBrian Starkey 		if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
10985e290226SAyan Kumar Halder 		    (map->pixel_formats[i].format == format)) {
10995e290226SAyan Kumar Halder 			/*
11005e290226SAyan Kumar Halder 			 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
11015e290226SAyan Kumar Halder 			 * is supported by a different h/w format id than
11025e290226SAyan Kumar Halder 			 * DRM_FORMAT_YUYV (only).
11035e290226SAyan Kumar Halder 			 */
11045e290226SAyan Kumar Halder 			if (format == DRM_FORMAT_YUYV &&
11055e290226SAyan Kumar Halder 			    (has_modifier) &&
11065e290226SAyan Kumar Halder 			    (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
11075e290226SAyan Kumar Halder 				return AFBC_YUV_422_FORMAT_ID;
11085e290226SAyan Kumar Halder 			else
11096211b486SBrian Starkey 				return map->pixel_formats[i].id;
1110ad49f860SLiviu Dudau 		}
11115e290226SAyan Kumar Halder 	}
1112ad49f860SLiviu Dudau 
1113ad49f860SLiviu Dudau 	return MALIDP_INVALID_FORMAT_ID;
1114ad49f860SLiviu Dudau }
1115ad49f860SLiviu Dudau 
malidp_hw_format_is_linear_only(u32 format)11165e290226SAyan Kumar Halder bool malidp_hw_format_is_linear_only(u32 format)
11175e290226SAyan Kumar Halder {
11185e290226SAyan Kumar Halder 	switch (format) {
11195e290226SAyan Kumar Halder 	case DRM_FORMAT_ARGB2101010:
11205e290226SAyan Kumar Halder 	case DRM_FORMAT_RGBA1010102:
11215e290226SAyan Kumar Halder 	case DRM_FORMAT_BGRA1010102:
11225e290226SAyan Kumar Halder 	case DRM_FORMAT_ARGB8888:
11235e290226SAyan Kumar Halder 	case DRM_FORMAT_RGBA8888:
11245e290226SAyan Kumar Halder 	case DRM_FORMAT_BGRA8888:
11255e290226SAyan Kumar Halder 	case DRM_FORMAT_XBGR8888:
11265e290226SAyan Kumar Halder 	case DRM_FORMAT_XRGB8888:
11275e290226SAyan Kumar Halder 	case DRM_FORMAT_RGBX8888:
11285e290226SAyan Kumar Halder 	case DRM_FORMAT_BGRX8888:
11295e290226SAyan Kumar Halder 	case DRM_FORMAT_RGB888:
11305e290226SAyan Kumar Halder 	case DRM_FORMAT_RGB565:
11315e290226SAyan Kumar Halder 	case DRM_FORMAT_ARGB1555:
11325e290226SAyan Kumar Halder 	case DRM_FORMAT_RGBA5551:
11335e290226SAyan Kumar Halder 	case DRM_FORMAT_BGRA5551:
11345e290226SAyan Kumar Halder 	case DRM_FORMAT_UYVY:
11355e290226SAyan Kumar Halder 	case DRM_FORMAT_XYUV8888:
11365e290226SAyan Kumar Halder 	case DRM_FORMAT_XVYU2101010:
11375e290226SAyan Kumar Halder 	case DRM_FORMAT_X0L2:
11385e290226SAyan Kumar Halder 	case DRM_FORMAT_X0L0:
11395e290226SAyan Kumar Halder 		return true;
11405e290226SAyan Kumar Halder 	default:
11415e290226SAyan Kumar Halder 		return false;
11425e290226SAyan Kumar Halder 	}
11435e290226SAyan Kumar Halder }
11445e290226SAyan Kumar Halder 
malidp_hw_format_is_afbc_only(u32 format)11455e290226SAyan Kumar Halder bool malidp_hw_format_is_afbc_only(u32 format)
11465e290226SAyan Kumar Halder {
11475e290226SAyan Kumar Halder 	switch (format) {
11485e290226SAyan Kumar Halder 	case DRM_FORMAT_VUY888:
11495e290226SAyan Kumar Halder 	case DRM_FORMAT_VUY101010:
11505e290226SAyan Kumar Halder 	case DRM_FORMAT_YUV420_8BIT:
11515e290226SAyan Kumar Halder 	case DRM_FORMAT_YUV420_10BIT:
11525e290226SAyan Kumar Halder 		return true;
11535e290226SAyan Kumar Halder 	default:
11545e290226SAyan Kumar Halder 		return false;
11555e290226SAyan Kumar Halder 	}
11565e290226SAyan Kumar Halder }
11575e290226SAyan Kumar Halder 
malidp_hw_clear_irq(struct malidp_hw_device * hwdev,u8 block,u32 irq)1158ad49f860SLiviu Dudau static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1159ad49f860SLiviu Dudau {
1160ad49f860SLiviu Dudau 	u32 base = malidp_get_block_base(hwdev, block);
1161ad49f860SLiviu Dudau 
1162a6993b21SLiviu Dudau 	if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1163ad49f860SLiviu Dudau 		malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1164ad49f860SLiviu Dudau 	else
1165ad49f860SLiviu Dudau 		malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1166ad49f860SLiviu Dudau }
1167ad49f860SLiviu Dudau 
malidp_de_irq(int irq,void * arg)1168ad49f860SLiviu Dudau static irqreturn_t malidp_de_irq(int irq, void *arg)
1169ad49f860SLiviu Dudau {
1170ad49f860SLiviu Dudau 	struct drm_device *drm = arg;
1171*1b93d3cbSDanilo Krummrich 	struct malidp_drm *malidp = drm_to_malidp(drm);
1172ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev;
1173a6993b21SLiviu Dudau 	struct malidp_hw *hw;
1174ad49f860SLiviu Dudau 	const struct malidp_irq_map *de;
1175ad49f860SLiviu Dudau 	u32 status, mask, dc_status;
1176ad49f860SLiviu Dudau 	irqreturn_t ret = IRQ_NONE;
1177ad49f860SLiviu Dudau 
1178ad49f860SLiviu Dudau 	hwdev = malidp->dev;
1179a6993b21SLiviu Dudau 	hw = hwdev->hw;
1180a6993b21SLiviu Dudau 	de = &hw->map.de_irq_map;
1181ad49f860SLiviu Dudau 
11820df34a80SLiviu Dudau 	/*
11830df34a80SLiviu Dudau 	 * if we are suspended it is likely that we were invoked because
11840df34a80SLiviu Dudau 	 * we share an interrupt line with some other driver, don't try
11850df34a80SLiviu Dudau 	 * to read the hardware registers
11860df34a80SLiviu Dudau 	 */
11870df34a80SLiviu Dudau 	if (hwdev->pm_suspended)
11880df34a80SLiviu Dudau 		return IRQ_NONE;
11890df34a80SLiviu Dudau 
1190ad49f860SLiviu Dudau 	/* first handle the config valid IRQ */
1191a6993b21SLiviu Dudau 	dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1192a6993b21SLiviu Dudau 	if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1193ad49f860SLiviu Dudau 		malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1194d862b2d6SLiviu Dudau 		/* do we have a page flip event? */
1195d862b2d6SLiviu Dudau 		if (malidp->event != NULL) {
1196d862b2d6SLiviu Dudau 			spin_lock(&drm->event_lock);
1197d862b2d6SLiviu Dudau 			drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1198d862b2d6SLiviu Dudau 			malidp->event = NULL;
1199d862b2d6SLiviu Dudau 			spin_unlock(&drm->event_lock);
1200d862b2d6SLiviu Dudau 		}
12011cb3cbe7SLiviu Dudau 		atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1202ad49f860SLiviu Dudau 		ret = IRQ_WAKE_THREAD;
1203ad49f860SLiviu Dudau 	}
1204ad49f860SLiviu Dudau 
1205ad49f860SLiviu Dudau 	status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1206ad49f860SLiviu Dudau 	if (!(status & de->irq_mask))
1207ad49f860SLiviu Dudau 		return ret;
1208ad49f860SLiviu Dudau 
1209ad49f860SLiviu Dudau 	mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1210613c5c7fSAlexandru Gheorghe 	/* keep the status of the enabled interrupts, plus the error bits */
1211613c5c7fSAlexandru Gheorghe 	status &= (mask | de->err_mask);
1212d862b2d6SLiviu Dudau 	if ((status & de->vsync_irq) && malidp->crtc.enabled)
1213ad49f860SLiviu Dudau 		drm_crtc_handle_vblank(&malidp->crtc);
1214ad49f860SLiviu Dudau 
1215613c5c7fSAlexandru Gheorghe #ifdef CONFIG_DEBUG_FS
1216613c5c7fSAlexandru Gheorghe 	if (status & de->err_mask) {
1217613c5c7fSAlexandru Gheorghe 		malidp_error(malidp, &malidp->de_errors, status,
1218613c5c7fSAlexandru Gheorghe 			     drm_crtc_vblank_count(&malidp->crtc));
1219613c5c7fSAlexandru Gheorghe 	}
1220613c5c7fSAlexandru Gheorghe #endif
1221ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1222ad49f860SLiviu Dudau 
1223ad49f860SLiviu Dudau 	return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1224ad49f860SLiviu Dudau }
1225ad49f860SLiviu Dudau 
malidp_de_irq_thread_handler(int irq,void * arg)1226ad49f860SLiviu Dudau static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1227ad49f860SLiviu Dudau {
1228ad49f860SLiviu Dudau 	struct drm_device *drm = arg;
1229*1b93d3cbSDanilo Krummrich 	struct malidp_drm *malidp = drm_to_malidp(drm);
1230ad49f860SLiviu Dudau 
1231ad49f860SLiviu Dudau 	wake_up(&malidp->wq);
1232ad49f860SLiviu Dudau 
1233ad49f860SLiviu Dudau 	return IRQ_HANDLED;
1234ad49f860SLiviu Dudau }
1235ad49f860SLiviu Dudau 
malidp_de_irq_hw_init(struct malidp_hw_device * hwdev)1236ff8fc26aSAyan Kumar Halder void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1237ff8fc26aSAyan Kumar Halder {
1238ff8fc26aSAyan Kumar Halder 	/* ensure interrupts are disabled */
1239ff8fc26aSAyan Kumar Halder 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1240ff8fc26aSAyan Kumar Halder 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1241ff8fc26aSAyan Kumar Halder 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1242ff8fc26aSAyan Kumar Halder 	malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1243ff8fc26aSAyan Kumar Halder 
1244ff8fc26aSAyan Kumar Halder 	/* first enable the DC block IRQs */
1245ff8fc26aSAyan Kumar Halder 	malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1246ff8fc26aSAyan Kumar Halder 			     hwdev->hw->map.dc_irq_map.irq_mask);
1247ff8fc26aSAyan Kumar Halder 
1248ff8fc26aSAyan Kumar Halder 	/* now enable the DE block IRQs */
1249ff8fc26aSAyan Kumar Halder 	malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1250ff8fc26aSAyan Kumar Halder 			     hwdev->hw->map.de_irq_map.irq_mask);
1251ff8fc26aSAyan Kumar Halder }
1252ff8fc26aSAyan Kumar Halder 
malidp_de_irq_init(struct drm_device * drm,int irq)1253ad49f860SLiviu Dudau int malidp_de_irq_init(struct drm_device *drm, int irq)
1254ad49f860SLiviu Dudau {
1255*1b93d3cbSDanilo Krummrich 	struct malidp_drm *malidp = drm_to_malidp(drm);
1256ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
1257ad49f860SLiviu Dudau 	int ret;
1258ad49f860SLiviu Dudau 
1259ad49f860SLiviu Dudau 	/* ensure interrupts are disabled */
1260ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1261ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1262ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1263ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1264ad49f860SLiviu Dudau 
1265ad49f860SLiviu Dudau 	ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1266ad49f860SLiviu Dudau 					malidp_de_irq_thread_handler,
1267ad49f860SLiviu Dudau 					IRQF_SHARED, "malidp-de", drm);
1268ad49f860SLiviu Dudau 	if (ret < 0) {
1269ad49f860SLiviu Dudau 		DRM_ERROR("failed to install DE IRQ handler\n");
1270ad49f860SLiviu Dudau 		return ret;
1271ad49f860SLiviu Dudau 	}
1272ad49f860SLiviu Dudau 
1273ff8fc26aSAyan Kumar Halder 	malidp_de_irq_hw_init(hwdev);
1274ad49f860SLiviu Dudau 
1275ad49f860SLiviu Dudau 	return 0;
1276ad49f860SLiviu Dudau }
1277ad49f860SLiviu Dudau 
malidp_de_irq_fini(struct malidp_hw_device * hwdev)127862862cfbSAyan Kumar Halder void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1279ad49f860SLiviu Dudau {
1280ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1281a6993b21SLiviu Dudau 			      hwdev->hw->map.de_irq_map.irq_mask);
1282ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1283a6993b21SLiviu Dudau 			      hwdev->hw->map.dc_irq_map.irq_mask);
1284ad49f860SLiviu Dudau }
1285ad49f860SLiviu Dudau 
malidp_se_irq(int irq,void * arg)1286ad49f860SLiviu Dudau static irqreturn_t malidp_se_irq(int irq, void *arg)
1287ad49f860SLiviu Dudau {
1288ad49f860SLiviu Dudau 	struct drm_device *drm = arg;
1289*1b93d3cbSDanilo Krummrich 	struct malidp_drm *malidp = drm_to_malidp(drm);
1290ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
1291a6993b21SLiviu Dudau 	struct malidp_hw *hw = hwdev->hw;
1292a6993b21SLiviu Dudau 	const struct malidp_irq_map *se = &hw->map.se_irq_map;
1293ad49f860SLiviu Dudau 	u32 status, mask;
1294ad49f860SLiviu Dudau 
12950df34a80SLiviu Dudau 	/*
12960df34a80SLiviu Dudau 	 * if we are suspended it is likely that we were invoked because
12970df34a80SLiviu Dudau 	 * we share an interrupt line with some other driver, don't try
12980df34a80SLiviu Dudau 	 * to read the hardware registers
12990df34a80SLiviu Dudau 	 */
13000df34a80SLiviu Dudau 	if (hwdev->pm_suspended)
13010df34a80SLiviu Dudau 		return IRQ_NONE;
13020df34a80SLiviu Dudau 
1303a6993b21SLiviu Dudau 	status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1304613c5c7fSAlexandru Gheorghe 	if (!(status & (se->irq_mask | se->err_mask)))
1305ad49f860SLiviu Dudau 		return IRQ_NONE;
1306ad49f860SLiviu Dudau 
1307613c5c7fSAlexandru Gheorghe #ifdef CONFIG_DEBUG_FS
1308613c5c7fSAlexandru Gheorghe 	if (status & se->err_mask)
1309613c5c7fSAlexandru Gheorghe 		malidp_error(malidp, &malidp->se_errors, status,
1310613c5c7fSAlexandru Gheorghe 			     drm_crtc_vblank_count(&malidp->crtc));
1311613c5c7fSAlexandru Gheorghe #endif
1312a6993b21SLiviu Dudau 	mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1313ad49f860SLiviu Dudau 	status &= mask;
13141cb3cbe7SLiviu Dudau 
13151cb3cbe7SLiviu Dudau 	if (status & se->vsync_irq) {
13161cb3cbe7SLiviu Dudau 		switch (hwdev->mw_state) {
13178cbc5cafSBrian Starkey 		case MW_ONESHOT:
13188cbc5cafSBrian Starkey 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
13198cbc5cafSBrian Starkey 			break;
13201cb3cbe7SLiviu Dudau 		case MW_STOP:
13218cbc5cafSBrian Starkey 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
13221cb3cbe7SLiviu Dudau 			/* disable writeback after stop */
13231cb3cbe7SLiviu Dudau 			hwdev->mw_state = MW_NOT_ENABLED;
13241cb3cbe7SLiviu Dudau 			break;
13250735cfdfSLiviu Dudau 		case MW_RESTART:
13260735cfdfSLiviu Dudau 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
1327df561f66SGustavo A. R. Silva 			fallthrough;	/* to a new start */
13281cb3cbe7SLiviu Dudau 		case MW_START:
13291cb3cbe7SLiviu Dudau 			/* writeback started, need to emulate one-shot mode */
13301cb3cbe7SLiviu Dudau 			hw->disable_memwrite(hwdev);
13311cb3cbe7SLiviu Dudau 			/*
13320735cfdfSLiviu Dudau 			 * only set config_valid HW bit if there is no other update
13330735cfdfSLiviu Dudau 			 * in progress or if we raced ahead of the DE IRQ handler
13340735cfdfSLiviu Dudau 			 * and config_valid flag will not be update until later
13351cb3cbe7SLiviu Dudau 			 */
13360735cfdfSLiviu Dudau 			status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
13370735cfdfSLiviu Dudau 			if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
13380735cfdfSLiviu Dudau 			    (status & hw->map.dc_irq_map.vsync_irq))
13390735cfdfSLiviu Dudau 				hw->set_config_valid(hwdev, 1);
13401cb3cbe7SLiviu Dudau 			break;
13411cb3cbe7SLiviu Dudau 		}
13421cb3cbe7SLiviu Dudau 	}
1343ad49f860SLiviu Dudau 
1344ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1345ad49f860SLiviu Dudau 
1346ad49f860SLiviu Dudau 	return IRQ_HANDLED;
1347ad49f860SLiviu Dudau }
1348ad49f860SLiviu Dudau 
malidp_se_irq_hw_init(struct malidp_hw_device * hwdev)1349ff8fc26aSAyan Kumar Halder void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1350ff8fc26aSAyan Kumar Halder {
1351ff8fc26aSAyan Kumar Halder 	/* ensure interrupts are disabled */
1352ff8fc26aSAyan Kumar Halder 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1353ff8fc26aSAyan Kumar Halder 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1354ff8fc26aSAyan Kumar Halder 
1355ff8fc26aSAyan Kumar Halder 	malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1356ff8fc26aSAyan Kumar Halder 			     hwdev->hw->map.se_irq_map.irq_mask);
1357ff8fc26aSAyan Kumar Halder }
1358ff8fc26aSAyan Kumar Halder 
malidp_se_irq_thread_handler(int irq,void * arg)1359ad49f860SLiviu Dudau static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1360ad49f860SLiviu Dudau {
1361ad49f860SLiviu Dudau 	return IRQ_HANDLED;
1362ad49f860SLiviu Dudau }
1363ad49f860SLiviu Dudau 
malidp_se_irq_init(struct drm_device * drm,int irq)1364ad49f860SLiviu Dudau int malidp_se_irq_init(struct drm_device *drm, int irq)
1365ad49f860SLiviu Dudau {
1366*1b93d3cbSDanilo Krummrich 	struct malidp_drm *malidp = drm_to_malidp(drm);
1367ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
1368ad49f860SLiviu Dudau 	int ret;
1369ad49f860SLiviu Dudau 
1370ad49f860SLiviu Dudau 	/* ensure interrupts are disabled */
1371ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1372ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1373ad49f860SLiviu Dudau 
1374ad49f860SLiviu Dudau 	ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1375ad49f860SLiviu Dudau 					malidp_se_irq_thread_handler,
1376ad49f860SLiviu Dudau 					IRQF_SHARED, "malidp-se", drm);
1377ad49f860SLiviu Dudau 	if (ret < 0) {
1378ad49f860SLiviu Dudau 		DRM_ERROR("failed to install SE IRQ handler\n");
1379ad49f860SLiviu Dudau 		return ret;
1380ad49f860SLiviu Dudau 	}
1381ad49f860SLiviu Dudau 
13821cb3cbe7SLiviu Dudau 	hwdev->mw_state = MW_NOT_ENABLED;
1383ff8fc26aSAyan Kumar Halder 	malidp_se_irq_hw_init(hwdev);
1384ad49f860SLiviu Dudau 
1385ad49f860SLiviu Dudau 	return 0;
1386ad49f860SLiviu Dudau }
1387ad49f860SLiviu Dudau 
malidp_se_irq_fini(struct malidp_hw_device * hwdev)138862862cfbSAyan Kumar Halder void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1389ad49f860SLiviu Dudau {
1390ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1391a6993b21SLiviu Dudau 			      hwdev->hw->map.se_irq_map.irq_mask);
1392ad49f860SLiviu Dudau }
1393