xref: /openbmc/linux/drivers/gpu/drm/arm/malidp_hw.c (revision 0735cfdf)
1ad49f860SLiviu Dudau /*
2ad49f860SLiviu Dudau  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
3ad49f860SLiviu Dudau  * Author: Liviu Dudau <Liviu.Dudau@arm.com>
4ad49f860SLiviu Dudau  *
5ad49f860SLiviu Dudau  * This program is free software and is provided to you under the terms of the
6ad49f860SLiviu Dudau  * GNU General Public License version 2 as published by the Free Software
7ad49f860SLiviu Dudau  * Foundation, and any use by you of this program is subject to the terms
8ad49f860SLiviu Dudau  * of such GNU licence.
9ad49f860SLiviu Dudau  *
10ad49f860SLiviu Dudau  * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
11ad49f860SLiviu Dudau  * the difference between various versions of the hardware is being dealt with
12ad49f860SLiviu Dudau  * in an attempt to provide to the rest of the driver code a unified view
13ad49f860SLiviu Dudau  */
14ad49f860SLiviu Dudau 
15c2e7f82dSMihail Atanassov #include <linux/clk.h>
16ad49f860SLiviu Dudau #include <linux/types.h>
17ad49f860SLiviu Dudau #include <linux/io.h>
18ad49f860SLiviu Dudau #include <drm/drmP.h>
19ad49f860SLiviu Dudau #include <video/videomode.h>
20ad49f860SLiviu Dudau #include <video/display_timing.h>
21ad49f860SLiviu Dudau 
22ad49f860SLiviu Dudau #include "malidp_drv.h"
23ad49f860SLiviu Dudau #include "malidp_hw.h"
248cbc5cafSBrian Starkey #include "malidp_mw.h"
25ad49f860SLiviu Dudau 
261cb3cbe7SLiviu Dudau enum {
271cb3cbe7SLiviu Dudau 	MW_NOT_ENABLED = 0,	/* SE writeback not enabled */
281cb3cbe7SLiviu Dudau 	MW_ONESHOT,		/* SE in one-shot mode for writeback */
291cb3cbe7SLiviu Dudau 	MW_START,		/* SE started writeback */
300735cfdfSLiviu Dudau 	MW_RESTART,		/* SE will start another writeback after this one */
310735cfdfSLiviu Dudau 	MW_STOP,		/* SE needs to stop after this writeback */
321cb3cbe7SLiviu Dudau };
331cb3cbe7SLiviu Dudau 
346211b486SBrian Starkey static const struct malidp_format_id malidp500_de_formats[] = {
35ad49f860SLiviu Dudau 	/*    fourcc,   layers supporting the format,     internal id  */
3609368e32SLiviu Dudau 	{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  0 },
3709368e32SLiviu Dudau 	{ DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  1 },
38ad49f860SLiviu Dudau 	{ DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  2 },
39ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  3 },
4009368e32SLiviu Dudau 	{ DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  4 },
4109368e32SLiviu Dudau 	{ DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  5 },
42ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  6 },
43ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  7 },
44ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  8 },
45ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  9 },
46ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
47ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
48ad49f860SLiviu Dudau 	{ DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
49ad49f860SLiviu Dudau 	{ DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
5009368e32SLiviu Dudau 	{ DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
51ad49f860SLiviu Dudau 	{ DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
52ad49f860SLiviu Dudau };
53ad49f860SLiviu Dudau 
54ad49f860SLiviu Dudau #define MALIDP_ID(__group, __format) \
55ad49f860SLiviu Dudau 	((((__group) & 0x7) << 3) | ((__format) & 0x7))
56ad49f860SLiviu Dudau 
57ad49f860SLiviu Dudau #define MALIDP_COMMON_FORMATS \
58ad49f860SLiviu Dudau 	/*    fourcc,   layers supporting the format,      internal id   */ \
59a67bbbe2SBrian Starkey 	{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
60a67bbbe2SBrian Starkey 	{ DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
61a67bbbe2SBrian Starkey 	{ DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
62a67bbbe2SBrian Starkey 	{ DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
63ad49f860SLiviu Dudau 	{ DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
64ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
65ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
66ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
67a67bbbe2SBrian Starkey 	{ DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
68a67bbbe2SBrian Starkey 	{ DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
69a67bbbe2SBrian Starkey 	{ DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
70a67bbbe2SBrian Starkey 	{ DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
71a67bbbe2SBrian Starkey 	{ DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
72a67bbbe2SBrian Starkey 	{ DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
73ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
74ad49f860SLiviu Dudau 	{ DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
75ad49f860SLiviu Dudau 	{ DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
76ad49f860SLiviu Dudau 	{ DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
77ad49f860SLiviu Dudau 	{ DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) },	\
78ad49f860SLiviu Dudau 	{ DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) },	\
79a67bbbe2SBrian Starkey 	{ DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) },	\
80ad49f860SLiviu Dudau 	{ DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }
81ad49f860SLiviu Dudau 
826211b486SBrian Starkey static const struct malidp_format_id malidp550_de_formats[] = {
83ad49f860SLiviu Dudau 	MALIDP_COMMON_FORMATS,
84ad49f860SLiviu Dudau };
85ad49f860SLiviu Dudau 
86ad49f860SLiviu Dudau static const struct malidp_layer malidp500_layers[] = {
876e810eb5SMihail Atanassov 	{ DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB },
886e810eb5SMihail Atanassov 	{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
896e810eb5SMihail Atanassov 	{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
90ad49f860SLiviu Dudau };
91ad49f860SLiviu Dudau 
92ad49f860SLiviu Dudau static const struct malidp_layer malidp550_layers[] = {
936e810eb5SMihail Atanassov 	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
946e810eb5SMihail Atanassov 	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
956e810eb5SMihail Atanassov 	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
966e810eb5SMihail Atanassov 	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE, 0 },
97ad49f860SLiviu Dudau };
98ad49f860SLiviu Dudau 
9928ce675bSMihail Atanassov #define SE_N_SCALING_COEFFS	96
10028ce675bSMihail Atanassov static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
10128ce675bSMihail Atanassov 	[MALIDP_UPSCALING_COEFFS - 1] = {
10228ce675bSMihail Atanassov 		0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
10328ce675bSMihail Atanassov 		0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
10428ce675bSMihail Atanassov 		0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
10528ce675bSMihail Atanassov 		0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
10628ce675bSMihail Atanassov 		0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
10728ce675bSMihail Atanassov 		0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
10828ce675bSMihail Atanassov 		0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
10928ce675bSMihail Atanassov 		0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
11028ce675bSMihail Atanassov 		0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
11128ce675bSMihail Atanassov 		0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
11228ce675bSMihail Atanassov 		0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
11328ce675bSMihail Atanassov 		0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
11428ce675bSMihail Atanassov 	},
11528ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
11628ce675bSMihail Atanassov 		0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
11728ce675bSMihail Atanassov 		0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
11828ce675bSMihail Atanassov 		0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
11928ce675bSMihail Atanassov 		0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
12028ce675bSMihail Atanassov 		0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
12128ce675bSMihail Atanassov 		0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
12228ce675bSMihail Atanassov 		0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
12328ce675bSMihail Atanassov 		0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
12428ce675bSMihail Atanassov 		0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
12528ce675bSMihail Atanassov 		0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
12628ce675bSMihail Atanassov 		0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
12728ce675bSMihail Atanassov 		0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
12828ce675bSMihail Atanassov 	},
12928ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_2_COEFFS - 1] = {
13028ce675bSMihail Atanassov 		0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
13128ce675bSMihail Atanassov 		0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
13228ce675bSMihail Atanassov 		0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
13328ce675bSMihail Atanassov 		0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
13428ce675bSMihail Atanassov 		0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
13528ce675bSMihail Atanassov 		0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
13628ce675bSMihail Atanassov 		0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
13728ce675bSMihail Atanassov 		0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
13828ce675bSMihail Atanassov 		0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
13928ce675bSMihail Atanassov 		0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
14028ce675bSMihail Atanassov 		0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
14128ce675bSMihail Atanassov 		0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
14228ce675bSMihail Atanassov 	},
14328ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
14428ce675bSMihail Atanassov 		0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
14528ce675bSMihail Atanassov 		0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
14628ce675bSMihail Atanassov 		0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
14728ce675bSMihail Atanassov 		0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
14828ce675bSMihail Atanassov 		0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
14928ce675bSMihail Atanassov 		0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
15028ce675bSMihail Atanassov 		0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
15128ce675bSMihail Atanassov 		0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
15228ce675bSMihail Atanassov 		0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
15328ce675bSMihail Atanassov 		0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
15428ce675bSMihail Atanassov 		0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
15528ce675bSMihail Atanassov 		0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
15628ce675bSMihail Atanassov 	},
15728ce675bSMihail Atanassov 	[MALIDP_DOWNSCALING_4_COEFFS - 1] = {
15828ce675bSMihail Atanassov 		0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
15928ce675bSMihail Atanassov 		0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
16028ce675bSMihail Atanassov 		0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
16128ce675bSMihail Atanassov 		0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
16228ce675bSMihail Atanassov 		0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
16328ce675bSMihail Atanassov 		0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
16428ce675bSMihail Atanassov 		0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
16528ce675bSMihail Atanassov 		0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
16628ce675bSMihail Atanassov 		0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
16728ce675bSMihail Atanassov 		0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
16828ce675bSMihail Atanassov 		0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
16928ce675bSMihail Atanassov 		0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
17028ce675bSMihail Atanassov 	},
17128ce675bSMihail Atanassov };
17228ce675bSMihail Atanassov 
173ad49f860SLiviu Dudau #define MALIDP_DE_DEFAULT_PREFETCH_START	5
174ad49f860SLiviu Dudau 
175ad49f860SLiviu Dudau static int malidp500_query_hw(struct malidp_hw_device *hwdev)
176ad49f860SLiviu Dudau {
177ad49f860SLiviu Dudau 	u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
178ad49f860SLiviu Dudau 	/* bit 4 of the CONFIG_ID register holds the line size multiplier */
179ad49f860SLiviu Dudau 	u8 ln_size_mult = conf & 0x10 ? 2 : 1;
180ad49f860SLiviu Dudau 
181ad49f860SLiviu Dudau 	hwdev->min_line_size = 2;
182ad49f860SLiviu Dudau 	hwdev->max_line_size = SZ_2K * ln_size_mult;
183ad49f860SLiviu Dudau 	hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
184ad49f860SLiviu Dudau 	hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
185ad49f860SLiviu Dudau 
186ad49f860SLiviu Dudau 	return 0;
187ad49f860SLiviu Dudau }
188ad49f860SLiviu Dudau 
189ad49f860SLiviu Dudau static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
190ad49f860SLiviu Dudau {
191ad49f860SLiviu Dudau 	u32 status, count = 100;
192ad49f860SLiviu Dudau 
193ad49f860SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
194ad49f860SLiviu Dudau 	while (count) {
195a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
196ad49f860SLiviu Dudau 		if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
197ad49f860SLiviu Dudau 			break;
198ad49f860SLiviu Dudau 		/*
199ad49f860SLiviu Dudau 		 * entering config mode can take as long as the rendering
200ad49f860SLiviu Dudau 		 * of a full frame, hence the long sleep here
201ad49f860SLiviu Dudau 		 */
202ad49f860SLiviu Dudau 		usleep_range(1000, 10000);
203ad49f860SLiviu Dudau 		count--;
204ad49f860SLiviu Dudau 	}
205ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while entering config mode");
206ad49f860SLiviu Dudau }
207ad49f860SLiviu Dudau 
208ad49f860SLiviu Dudau static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
209ad49f860SLiviu Dudau {
210ad49f860SLiviu Dudau 	u32 status, count = 100;
211ad49f860SLiviu Dudau 
212e64053f0SBrian Starkey 	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
213ad49f860SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
214ad49f860SLiviu Dudau 	while (count) {
215a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
216ad49f860SLiviu Dudau 		if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
217ad49f860SLiviu Dudau 			break;
218ad49f860SLiviu Dudau 		usleep_range(100, 1000);
219ad49f860SLiviu Dudau 		count--;
220ad49f860SLiviu Dudau 	}
221ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while leaving config mode");
222ad49f860SLiviu Dudau }
223ad49f860SLiviu Dudau 
224ad49f860SLiviu Dudau static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
225ad49f860SLiviu Dudau {
226ad49f860SLiviu Dudau 	u32 status;
227ad49f860SLiviu Dudau 
228a6993b21SLiviu Dudau 	status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
229ad49f860SLiviu Dudau 	if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
230ad49f860SLiviu Dudau 		return true;
231ad49f860SLiviu Dudau 
232ad49f860SLiviu Dudau 	return false;
233ad49f860SLiviu Dudau }
234ad49f860SLiviu Dudau 
2350735cfdfSLiviu Dudau static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
236ad49f860SLiviu Dudau {
2370735cfdfSLiviu Dudau 	if (value)
238ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
2390735cfdfSLiviu Dudau 	else
2400735cfdfSLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
241ad49f860SLiviu Dudau }
242ad49f860SLiviu Dudau 
243ad49f860SLiviu Dudau static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
244ad49f860SLiviu Dudau {
245ad49f860SLiviu Dudau 	u32 val = 0;
246ad49f860SLiviu Dudau 
247ad49f860SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
248ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
249ad49f860SLiviu Dudau 		val |= MALIDP500_HSYNCPOL;
250ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
251ad49f860SLiviu Dudau 		val |= MALIDP500_VSYNCPOL;
252ad49f860SLiviu Dudau 	val |= MALIDP_DE_DEFAULT_PREFETCH_START;
253ad49f860SLiviu Dudau 	malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
254ad49f860SLiviu Dudau 
255ad49f860SLiviu Dudau 	/*
256ad49f860SLiviu Dudau 	 * Mali-DP500 encodes the background color like this:
257ad49f860SLiviu Dudau 	 *    - red   @ MALIDP500_BGND_COLOR[12:0]
258ad49f860SLiviu Dudau 	 *    - green @ MALIDP500_BGND_COLOR[27:16]
259ad49f860SLiviu Dudau 	 *    - blue  @ (MALIDP500_BGND_COLOR + 4)[12:0]
260ad49f860SLiviu Dudau 	 */
261ad49f860SLiviu Dudau 	val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
262ad49f860SLiviu Dudau 	      (MALIDP_BGND_COLOR_R & 0xfff);
263ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
264ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
265ad49f860SLiviu Dudau 
266ad49f860SLiviu Dudau 	val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
267ad49f860SLiviu Dudau 		MALIDP_DE_H_BACKPORCH(mode->hback_porch);
268ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
269ad49f860SLiviu Dudau 
270ad49f860SLiviu Dudau 	val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
271ad49f860SLiviu Dudau 		MALIDP_DE_V_BACKPORCH(mode->vback_porch);
272ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
273ad49f860SLiviu Dudau 
274ad49f860SLiviu Dudau 	val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
275ad49f860SLiviu Dudau 		MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
276ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
277ad49f860SLiviu Dudau 
278ad49f860SLiviu Dudau 	val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
279ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
280ad49f860SLiviu Dudau 
281ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
282ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
283ad49f860SLiviu Dudau 	else
284ad49f860SLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
285ad49f860SLiviu Dudau }
286ad49f860SLiviu Dudau 
287ad49f860SLiviu Dudau static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
288ad49f860SLiviu Dudau {
289ad49f860SLiviu Dudau 	/* RGB888 or BGR888 can't be rotated */
290ad49f860SLiviu Dudau 	if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
291ad49f860SLiviu Dudau 		return -EINVAL;
292ad49f860SLiviu Dudau 
293ad49f860SLiviu Dudau 	/*
294ad49f860SLiviu Dudau 	 * Each layer needs enough rotation memory to fit 8 lines
295ad49f860SLiviu Dudau 	 * worth of pixel data. Required size is then:
296ad49f860SLiviu Dudau 	 *    size = rotated_width * (bpp / 8) * 8;
297ad49f860SLiviu Dudau 	 */
2987ccf281fSLaurent Pinchart 	return w * drm_format_plane_cpp(fmt, 0) * 8;
299ad49f860SLiviu Dudau }
300ad49f860SLiviu Dudau 
30128ce675bSMihail Atanassov static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
30228ce675bSMihail Atanassov 					   u32 direction,
30328ce675bSMihail Atanassov 					   u16 addr,
30428ce675bSMihail Atanassov 					   u8 coeffs_id)
30528ce675bSMihail Atanassov {
30628ce675bSMihail Atanassov 	int i;
30728ce675bSMihail Atanassov 	u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
30828ce675bSMihail Atanassov 
30928ce675bSMihail Atanassov 	malidp_hw_write(hwdev,
31028ce675bSMihail Atanassov 			direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
31128ce675bSMihail Atanassov 			scaling_control + MALIDP_SE_COEFFTAB_ADDR);
31228ce675bSMihail Atanassov 	for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
31328ce675bSMihail Atanassov 		malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
31428ce675bSMihail Atanassov 				dp500_se_scaling_coeffs[coeffs_id][i]),
31528ce675bSMihail Atanassov 				scaling_control + MALIDP_SE_COEFFTAB_DATA);
31628ce675bSMihail Atanassov }
31728ce675bSMihail Atanassov 
31828ce675bSMihail Atanassov static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
31928ce675bSMihail Atanassov 					   struct malidp_se_config *se_config,
32028ce675bSMihail Atanassov 					   struct malidp_se_config *old_config)
32128ce675bSMihail Atanassov {
32228ce675bSMihail Atanassov 	/* Get array indices into dp500_se_scaling_coeffs. */
32328ce675bSMihail Atanassov 	u8 h = (u8)se_config->hcoeff - 1;
32428ce675bSMihail Atanassov 	u8 v = (u8)se_config->vcoeff - 1;
32528ce675bSMihail Atanassov 
32628ce675bSMihail Atanassov 	if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
32728ce675bSMihail Atanassov 		    v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
32828ce675bSMihail Atanassov 		return -EINVAL;
32928ce675bSMihail Atanassov 
33028ce675bSMihail Atanassov 	if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
33128ce675bSMihail Atanassov 			 se_config->vcoeff != old_config->vcoeff)) {
33228ce675bSMihail Atanassov 		malidp500_se_write_pp_coefftab(hwdev,
33328ce675bSMihail Atanassov 					       (MALIDP_SE_V_COEFFTAB |
33428ce675bSMihail Atanassov 						MALIDP_SE_H_COEFFTAB),
33528ce675bSMihail Atanassov 					       0, v);
33628ce675bSMihail Atanassov 	} else {
33728ce675bSMihail Atanassov 		if (se_config->vcoeff != old_config->vcoeff)
33828ce675bSMihail Atanassov 			malidp500_se_write_pp_coefftab(hwdev,
33928ce675bSMihail Atanassov 						       MALIDP_SE_V_COEFFTAB,
34028ce675bSMihail Atanassov 						       0, v);
34128ce675bSMihail Atanassov 		if (se_config->hcoeff != old_config->hcoeff)
34228ce675bSMihail Atanassov 			malidp500_se_write_pp_coefftab(hwdev,
34328ce675bSMihail Atanassov 						       MALIDP_SE_H_COEFFTAB,
34428ce675bSMihail Atanassov 						       0, h);
34528ce675bSMihail Atanassov 	}
34628ce675bSMihail Atanassov 
34728ce675bSMihail Atanassov 	return 0;
34828ce675bSMihail Atanassov }
34928ce675bSMihail Atanassov 
350c2e7f82dSMihail Atanassov static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
351c2e7f82dSMihail Atanassov 				   struct malidp_se_config *se_config,
352c2e7f82dSMihail Atanassov 				   struct videomode *vm)
353c2e7f82dSMihail Atanassov {
354c2e7f82dSMihail Atanassov 	unsigned long mclk;
355c2e7f82dSMihail Atanassov 	unsigned long pxlclk = vm->pixelclock; /* Hz */
356c2e7f82dSMihail Atanassov 	unsigned long htotal = vm->hactive + vm->hfront_porch +
357c2e7f82dSMihail Atanassov 			       vm->hback_porch + vm->hsync_len;
358c2e7f82dSMihail Atanassov 	unsigned long input_size = se_config->input_w * se_config->input_h;
359c2e7f82dSMihail Atanassov 	unsigned long a = 10;
360c2e7f82dSMihail Atanassov 	long ret;
361c2e7f82dSMihail Atanassov 
362c2e7f82dSMihail Atanassov 	/*
363c2e7f82dSMihail Atanassov 	 * mclk = max(a, 1.5) * pxlclk
364c2e7f82dSMihail Atanassov 	 *
365c2e7f82dSMihail Atanassov 	 * To avoid float calculaiton, using 15 instead of 1.5 and div by
366c2e7f82dSMihail Atanassov 	 * 10 to get mclk.
367c2e7f82dSMihail Atanassov 	 */
368c2e7f82dSMihail Atanassov 	if (se_config->scale_enable) {
369c2e7f82dSMihail Atanassov 		a = 15 * input_size / (htotal * se_config->output_h);
370c2e7f82dSMihail Atanassov 		if (a < 15)
371c2e7f82dSMihail Atanassov 			a = 15;
372c2e7f82dSMihail Atanassov 	}
373c2e7f82dSMihail Atanassov 	mclk = a * pxlclk / 10;
374c2e7f82dSMihail Atanassov 	ret = clk_get_rate(hwdev->mclk);
375c2e7f82dSMihail Atanassov 	if (ret < mclk) {
376c2e7f82dSMihail Atanassov 		DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
377c2e7f82dSMihail Atanassov 				 mclk / 1000);
378c2e7f82dSMihail Atanassov 		return -EINVAL;
379c2e7f82dSMihail Atanassov 	}
380c2e7f82dSMihail Atanassov 	return ret;
381c2e7f82dSMihail Atanassov }
382c2e7f82dSMihail Atanassov 
3831cb3cbe7SLiviu Dudau static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
3841cb3cbe7SLiviu Dudau 				     dma_addr_t *addrs, s32 *pitches,
3851cb3cbe7SLiviu Dudau 				     int num_planes, u16 w, u16 h, u32 fmt_id)
3861cb3cbe7SLiviu Dudau {
3871cb3cbe7SLiviu Dudau 	u32 base = MALIDP500_SE_MEMWRITE_BASE;
3881cb3cbe7SLiviu Dudau 	u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
3891cb3cbe7SLiviu Dudau 
3901cb3cbe7SLiviu Dudau 	/* enable the scaling engine block */
3911cb3cbe7SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
3921cb3cbe7SLiviu Dudau 
3930735cfdfSLiviu Dudau 	/* restart the writeback if already enabled */
3940735cfdfSLiviu Dudau 	if (hwdev->mw_state != MW_NOT_ENABLED)
3950735cfdfSLiviu Dudau 		hwdev->mw_state = MW_RESTART;
3960735cfdfSLiviu Dudau 	else
3971cb3cbe7SLiviu Dudau 		hwdev->mw_state = MW_START;
3981cb3cbe7SLiviu Dudau 
3991cb3cbe7SLiviu Dudau 	malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
4001cb3cbe7SLiviu Dudau 	switch (num_planes) {
4011cb3cbe7SLiviu Dudau 	case 2:
4021cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
4031cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
4041cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
4051cb3cbe7SLiviu Dudau 		/* fall through */
4061cb3cbe7SLiviu Dudau 	case 1:
4071cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
4081cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
4091cb3cbe7SLiviu Dudau 		malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
4101cb3cbe7SLiviu Dudau 		break;
4111cb3cbe7SLiviu Dudau 	default:
4121cb3cbe7SLiviu Dudau 		WARN(1, "Invalid number of planes");
4131cb3cbe7SLiviu Dudau 	}
4141cb3cbe7SLiviu Dudau 
4151cb3cbe7SLiviu Dudau 	malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
4161cb3cbe7SLiviu Dudau 			MALIDP500_SE_MEMWRITE_OUT_SIZE);
4171cb3cbe7SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
4181cb3cbe7SLiviu Dudau 
4191cb3cbe7SLiviu Dudau 	return 0;
4201cb3cbe7SLiviu Dudau }
4211cb3cbe7SLiviu Dudau 
4221cb3cbe7SLiviu Dudau static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
4231cb3cbe7SLiviu Dudau {
4241cb3cbe7SLiviu Dudau 	u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
4251cb3cbe7SLiviu Dudau 
4260735cfdfSLiviu Dudau 	if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
4271cb3cbe7SLiviu Dudau 		hwdev->mw_state = MW_STOP;
4281cb3cbe7SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
4291cb3cbe7SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
4301cb3cbe7SLiviu Dudau }
4311cb3cbe7SLiviu Dudau 
432ad49f860SLiviu Dudau static int malidp550_query_hw(struct malidp_hw_device *hwdev)
433ad49f860SLiviu Dudau {
434ad49f860SLiviu Dudau 	u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
435ad49f860SLiviu Dudau 	u8 ln_size = (conf >> 4) & 0x3, rsize;
436ad49f860SLiviu Dudau 
437ad49f860SLiviu Dudau 	hwdev->min_line_size = 2;
438ad49f860SLiviu Dudau 
439ad49f860SLiviu Dudau 	switch (ln_size) {
440ad49f860SLiviu Dudau 	case 0:
441ad49f860SLiviu Dudau 		hwdev->max_line_size = SZ_2K;
442ad49f860SLiviu Dudau 		/* two banks of 64KB for rotation memory */
443ad49f860SLiviu Dudau 		rsize = 64;
444ad49f860SLiviu Dudau 		break;
445ad49f860SLiviu Dudau 	case 1:
446ad49f860SLiviu Dudau 		hwdev->max_line_size = SZ_4K;
447ad49f860SLiviu Dudau 		/* two banks of 128KB for rotation memory */
448ad49f860SLiviu Dudau 		rsize = 128;
449ad49f860SLiviu Dudau 		break;
450ad49f860SLiviu Dudau 	case 2:
451ad49f860SLiviu Dudau 		hwdev->max_line_size = 1280;
452ad49f860SLiviu Dudau 		/* two banks of 40KB for rotation memory */
453ad49f860SLiviu Dudau 		rsize = 40;
454ad49f860SLiviu Dudau 		break;
455ad49f860SLiviu Dudau 	case 3:
456ad49f860SLiviu Dudau 		/* reserved value */
457ad49f860SLiviu Dudau 		hwdev->max_line_size = 0;
458ad49f860SLiviu Dudau 		return -EINVAL;
459ad49f860SLiviu Dudau 	}
460ad49f860SLiviu Dudau 
461ad49f860SLiviu Dudau 	hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
462ad49f860SLiviu Dudau 	return 0;
463ad49f860SLiviu Dudau }
464ad49f860SLiviu Dudau 
465ad49f860SLiviu Dudau static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
466ad49f860SLiviu Dudau {
467ad49f860SLiviu Dudau 	u32 status, count = 100;
468ad49f860SLiviu Dudau 
469ad49f860SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
470ad49f860SLiviu Dudau 	while (count) {
471a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
472ad49f860SLiviu Dudau 		if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
473ad49f860SLiviu Dudau 			break;
474ad49f860SLiviu Dudau 		/*
475ad49f860SLiviu Dudau 		 * entering config mode can take as long as the rendering
476ad49f860SLiviu Dudau 		 * of a full frame, hence the long sleep here
477ad49f860SLiviu Dudau 		 */
478ad49f860SLiviu Dudau 		usleep_range(1000, 10000);
479ad49f860SLiviu Dudau 		count--;
480ad49f860SLiviu Dudau 	}
481ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while entering config mode");
482ad49f860SLiviu Dudau }
483ad49f860SLiviu Dudau 
484ad49f860SLiviu Dudau static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
485ad49f860SLiviu Dudau {
486ad49f860SLiviu Dudau 	u32 status, count = 100;
487ad49f860SLiviu Dudau 
488e64053f0SBrian Starkey 	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
489ad49f860SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
490ad49f860SLiviu Dudau 	while (count) {
491a6993b21SLiviu Dudau 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
492ad49f860SLiviu Dudau 		if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
493ad49f860SLiviu Dudau 			break;
494ad49f860SLiviu Dudau 		usleep_range(100, 1000);
495ad49f860SLiviu Dudau 		count--;
496ad49f860SLiviu Dudau 	}
497ad49f860SLiviu Dudau 	WARN(count == 0, "timeout while leaving config mode");
498ad49f860SLiviu Dudau }
499ad49f860SLiviu Dudau 
500ad49f860SLiviu Dudau static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
501ad49f860SLiviu Dudau {
502ad49f860SLiviu Dudau 	u32 status;
503ad49f860SLiviu Dudau 
504a6993b21SLiviu Dudau 	status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
505ad49f860SLiviu Dudau 	if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
506ad49f860SLiviu Dudau 		return true;
507ad49f860SLiviu Dudau 
508ad49f860SLiviu Dudau 	return false;
509ad49f860SLiviu Dudau }
510ad49f860SLiviu Dudau 
5110735cfdfSLiviu Dudau static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
512ad49f860SLiviu Dudau {
5130735cfdfSLiviu Dudau 	if (value)
514ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
5150735cfdfSLiviu Dudau 	else
5160735cfdfSLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
517ad49f860SLiviu Dudau }
518ad49f860SLiviu Dudau 
519ad49f860SLiviu Dudau static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
520ad49f860SLiviu Dudau {
521ad49f860SLiviu Dudau 	u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
522ad49f860SLiviu Dudau 
523ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
524ad49f860SLiviu Dudau 	/*
525ad49f860SLiviu Dudau 	 * Mali-DP550 and Mali-DP650 encode the background color like this:
526ad49f860SLiviu Dudau 	 *   - red   @ MALIDP550_DE_BGND_COLOR[23:16]
527ad49f860SLiviu Dudau 	 *   - green @ MALIDP550_DE_BGND_COLOR[15:8]
528ad49f860SLiviu Dudau 	 *   - blue  @ MALIDP550_DE_BGND_COLOR[7:0]
529ad49f860SLiviu Dudau 	 *
530ad49f860SLiviu Dudau 	 * We need to truncate the least significant 4 bits from the default
531ad49f860SLiviu Dudau 	 * MALIDP_BGND_COLOR_x values
532ad49f860SLiviu Dudau 	 */
533ad49f860SLiviu Dudau 	val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
534ad49f860SLiviu Dudau 	      (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
535ad49f860SLiviu Dudau 	      ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
536ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
537ad49f860SLiviu Dudau 
538ad49f860SLiviu Dudau 	val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
539ad49f860SLiviu Dudau 		MALIDP_DE_H_BACKPORCH(mode->hback_porch);
540ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
541ad49f860SLiviu Dudau 
542ad49f860SLiviu Dudau 	val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
543ad49f860SLiviu Dudau 		MALIDP_DE_V_BACKPORCH(mode->vback_porch);
544ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
545ad49f860SLiviu Dudau 
546ad49f860SLiviu Dudau 	val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
547ad49f860SLiviu Dudau 		MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
548ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
549ad49f860SLiviu Dudau 		val |= MALIDP550_HSYNCPOL;
550ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
551ad49f860SLiviu Dudau 		val |= MALIDP550_VSYNCPOL;
552ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
553ad49f860SLiviu Dudau 
554ad49f860SLiviu Dudau 	val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
555ad49f860SLiviu Dudau 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
556ad49f860SLiviu Dudau 
557ad49f860SLiviu Dudau 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
558ad49f860SLiviu Dudau 		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
559ad49f860SLiviu Dudau 	else
560ad49f860SLiviu Dudau 		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
561ad49f860SLiviu Dudau }
562ad49f860SLiviu Dudau 
563ad49f860SLiviu Dudau static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
564ad49f860SLiviu Dudau {
565ad49f860SLiviu Dudau 	u32 bytes_per_col;
566ad49f860SLiviu Dudau 
567ad49f860SLiviu Dudau 	/* raw RGB888 or BGR888 can't be rotated */
568ad49f860SLiviu Dudau 	if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
569ad49f860SLiviu Dudau 		return -EINVAL;
570ad49f860SLiviu Dudau 
571ad49f860SLiviu Dudau 	switch (fmt) {
572ad49f860SLiviu Dudau 	/* 8 lines at 4 bytes per pixel */
573ad49f860SLiviu Dudau 	case DRM_FORMAT_ARGB2101010:
574ad49f860SLiviu Dudau 	case DRM_FORMAT_ABGR2101010:
575ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBA1010102:
576ad49f860SLiviu Dudau 	case DRM_FORMAT_BGRA1010102:
577ad49f860SLiviu Dudau 	case DRM_FORMAT_ARGB8888:
578ad49f860SLiviu Dudau 	case DRM_FORMAT_ABGR8888:
579ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBA8888:
580ad49f860SLiviu Dudau 	case DRM_FORMAT_BGRA8888:
581ad49f860SLiviu Dudau 	case DRM_FORMAT_XRGB8888:
582ad49f860SLiviu Dudau 	case DRM_FORMAT_XBGR8888:
583ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBX8888:
584ad49f860SLiviu Dudau 	case DRM_FORMAT_BGRX8888:
585ad49f860SLiviu Dudau 	case DRM_FORMAT_RGB888:
586ad49f860SLiviu Dudau 	case DRM_FORMAT_BGR888:
587ad49f860SLiviu Dudau 	/* 16 lines at 2 bytes per pixel */
588ad49f860SLiviu Dudau 	case DRM_FORMAT_RGBA5551:
589ad49f860SLiviu Dudau 	case DRM_FORMAT_ABGR1555:
590ad49f860SLiviu Dudau 	case DRM_FORMAT_RGB565:
591ad49f860SLiviu Dudau 	case DRM_FORMAT_BGR565:
592ad49f860SLiviu Dudau 	case DRM_FORMAT_UYVY:
593ad49f860SLiviu Dudau 	case DRM_FORMAT_YUYV:
594ad49f860SLiviu Dudau 		bytes_per_col = 32;
595ad49f860SLiviu Dudau 		break;
596ad49f860SLiviu Dudau 	/* 16 lines at 1.5 bytes per pixel */
597ad49f860SLiviu Dudau 	case DRM_FORMAT_NV12:
598ad49f860SLiviu Dudau 	case DRM_FORMAT_YUV420:
599ad49f860SLiviu Dudau 		bytes_per_col = 24;
600ad49f860SLiviu Dudau 		break;
601ad49f860SLiviu Dudau 	default:
602ad49f860SLiviu Dudau 		return -EINVAL;
603ad49f860SLiviu Dudau 	}
604ad49f860SLiviu Dudau 
605ad49f860SLiviu Dudau 	return w * bytes_per_col;
606ad49f860SLiviu Dudau }
607ad49f860SLiviu Dudau 
60828ce675bSMihail Atanassov static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
60928ce675bSMihail Atanassov 					   struct malidp_se_config *se_config,
61028ce675bSMihail Atanassov 					   struct malidp_se_config *old_config)
61128ce675bSMihail Atanassov {
61228ce675bSMihail Atanassov 	u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
61328ce675bSMihail Atanassov 		   MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
61428ce675bSMihail Atanassov 	u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
61528ce675bSMihail Atanassov 			MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
61628ce675bSMihail Atanassov 
61728ce675bSMihail Atanassov 	malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
61828ce675bSMihail Atanassov 	malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
61928ce675bSMihail Atanassov 	return 0;
62028ce675bSMihail Atanassov }
62128ce675bSMihail Atanassov 
622c2e7f82dSMihail Atanassov static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
623c2e7f82dSMihail Atanassov 				   struct malidp_se_config *se_config,
624c2e7f82dSMihail Atanassov 				   struct videomode *vm)
625c2e7f82dSMihail Atanassov {
626c2e7f82dSMihail Atanassov 	unsigned long mclk;
627c2e7f82dSMihail Atanassov 	unsigned long pxlclk = vm->pixelclock;
628c2e7f82dSMihail Atanassov 	unsigned long htotal = vm->hactive + vm->hfront_porch +
629c2e7f82dSMihail Atanassov 			       vm->hback_porch + vm->hsync_len;
630c2e7f82dSMihail Atanassov 	unsigned long numerator = 1, denominator = 1;
631c2e7f82dSMihail Atanassov 	long ret;
632c2e7f82dSMihail Atanassov 
633c2e7f82dSMihail Atanassov 	if (se_config->scale_enable) {
634c2e7f82dSMihail Atanassov 		numerator = max(se_config->input_w, se_config->output_w) *
635c2e7f82dSMihail Atanassov 			    se_config->input_h;
636c2e7f82dSMihail Atanassov 		numerator += se_config->output_w *
637c2e7f82dSMihail Atanassov 			     (se_config->output_h -
638c2e7f82dSMihail Atanassov 			      min(se_config->input_h, se_config->output_h));
639c2e7f82dSMihail Atanassov 		denominator = (htotal - 2) * se_config->output_h;
640c2e7f82dSMihail Atanassov 	}
641c2e7f82dSMihail Atanassov 
642c2e7f82dSMihail Atanassov 	/* mclk can't be slower than pxlclk. */
643c2e7f82dSMihail Atanassov 	if (numerator < denominator)
644c2e7f82dSMihail Atanassov 		numerator = denominator = 1;
645c2e7f82dSMihail Atanassov 	mclk = (pxlclk * numerator) / denominator;
646c2e7f82dSMihail Atanassov 	ret = clk_get_rate(hwdev->mclk);
647c2e7f82dSMihail Atanassov 	if (ret < mclk) {
648c2e7f82dSMihail Atanassov 		DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
649c2e7f82dSMihail Atanassov 				 mclk / 1000);
650c2e7f82dSMihail Atanassov 		return -EINVAL;
651c2e7f82dSMihail Atanassov 	}
652c2e7f82dSMihail Atanassov 	return ret;
653c2e7f82dSMihail Atanassov }
654c2e7f82dSMihail Atanassov 
655846c87a0SLiviu Dudau static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
656846c87a0SLiviu Dudau 				     dma_addr_t *addrs, s32 *pitches,
657846c87a0SLiviu Dudau 				     int num_planes, u16 w, u16 h, u32 fmt_id)
658846c87a0SLiviu Dudau {
659846c87a0SLiviu Dudau 	u32 base = MALIDP550_SE_MEMWRITE_BASE;
660846c87a0SLiviu Dudau 	u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
661846c87a0SLiviu Dudau 
662846c87a0SLiviu Dudau 	/* enable the scaling engine block */
663846c87a0SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
664846c87a0SLiviu Dudau 
6651cb3cbe7SLiviu Dudau 	hwdev->mw_state = MW_ONESHOT;
6661cb3cbe7SLiviu Dudau 
667846c87a0SLiviu Dudau 	malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
668846c87a0SLiviu Dudau 	switch (num_planes) {
669846c87a0SLiviu Dudau 	case 2:
670846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
671846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
672846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
673846c87a0SLiviu Dudau 		/* fall through */
674846c87a0SLiviu Dudau 	case 1:
675846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
676846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
677846c87a0SLiviu Dudau 		malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
678846c87a0SLiviu Dudau 		break;
679846c87a0SLiviu Dudau 	default:
680846c87a0SLiviu Dudau 		WARN(1, "Invalid number of planes");
681846c87a0SLiviu Dudau 	}
682846c87a0SLiviu Dudau 
683846c87a0SLiviu Dudau 	malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
684846c87a0SLiviu Dudau 			MALIDP550_SE_MEMWRITE_OUT_SIZE);
685846c87a0SLiviu Dudau 	malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
686846c87a0SLiviu Dudau 			  MALIDP550_SE_CONTROL);
687846c87a0SLiviu Dudau 
688846c87a0SLiviu Dudau 	return 0;
689846c87a0SLiviu Dudau }
690846c87a0SLiviu Dudau 
691846c87a0SLiviu Dudau static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
692846c87a0SLiviu Dudau {
693846c87a0SLiviu Dudau 	u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
694846c87a0SLiviu Dudau 
695846c87a0SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
696846c87a0SLiviu Dudau 			    MALIDP550_SE_CONTROL);
697846c87a0SLiviu Dudau 	malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
698846c87a0SLiviu Dudau }
699846c87a0SLiviu Dudau 
700ad49f860SLiviu Dudau static int malidp650_query_hw(struct malidp_hw_device *hwdev)
701ad49f860SLiviu Dudau {
702ad49f860SLiviu Dudau 	u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
703ad49f860SLiviu Dudau 	u8 ln_size = (conf >> 4) & 0x3, rsize;
704ad49f860SLiviu Dudau 
705ad49f860SLiviu Dudau 	hwdev->min_line_size = 4;
706ad49f860SLiviu Dudau 
707ad49f860SLiviu Dudau 	switch (ln_size) {
708ad49f860SLiviu Dudau 	case 0:
709ad49f860SLiviu Dudau 	case 2:
710ad49f860SLiviu Dudau 		/* reserved values */
711ad49f860SLiviu Dudau 		hwdev->max_line_size = 0;
712ad49f860SLiviu Dudau 		return -EINVAL;
713ad49f860SLiviu Dudau 	case 1:
714ad49f860SLiviu Dudau 		hwdev->max_line_size = SZ_4K;
715ad49f860SLiviu Dudau 		/* two banks of 128KB for rotation memory */
716ad49f860SLiviu Dudau 		rsize = 128;
717ad49f860SLiviu Dudau 		break;
718ad49f860SLiviu Dudau 	case 3:
719ad49f860SLiviu Dudau 		hwdev->max_line_size = 2560;
720ad49f860SLiviu Dudau 		/* two banks of 80KB for rotation memory */
721ad49f860SLiviu Dudau 		rsize = 80;
722ad49f860SLiviu Dudau 	}
723ad49f860SLiviu Dudau 
724ad49f860SLiviu Dudau 	hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
725ad49f860SLiviu Dudau 	return 0;
726ad49f860SLiviu Dudau }
727ad49f860SLiviu Dudau 
728a6993b21SLiviu Dudau const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
729ad49f860SLiviu Dudau 	[MALIDP_500] = {
730ad49f860SLiviu Dudau 		.map = {
73102725d31SMihail Atanassov 			.coeffs_base = MALIDP500_COEFFS_BASE,
732ad49f860SLiviu Dudau 			.se_base = MALIDP500_SE_BASE,
733ad49f860SLiviu Dudau 			.dc_base = MALIDP500_DC_BASE,
734ad49f860SLiviu Dudau 			.out_depth_base = MALIDP500_OUTPUT_DEPTH,
735ad49f860SLiviu Dudau 			.features = 0,	/* no CLEARIRQ register */
736ad49f860SLiviu Dudau 			.n_layers = ARRAY_SIZE(malidp500_layers),
737ad49f860SLiviu Dudau 			.layers = malidp500_layers,
738ad49f860SLiviu Dudau 			.de_irq_map = {
739ad49f860SLiviu Dudau 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
740ad49f860SLiviu Dudau 					    MALIDP500_DE_IRQ_AXI_ERR |
741ad49f860SLiviu Dudau 					    MALIDP500_DE_IRQ_VSYNC |
742ad49f860SLiviu Dudau 					    MALIDP500_DE_IRQ_GLOBAL,
743ad49f860SLiviu Dudau 				.vsync_irq = MALIDP500_DE_IRQ_VSYNC,
744ad49f860SLiviu Dudau 			},
745ad49f860SLiviu Dudau 			.se_irq_map = {
74689610dc2SAlison Wang 				.irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
7471cb3cbe7SLiviu Dudau 					    MALIDP500_SE_IRQ_CONF_VALID |
74889610dc2SAlison Wang 					    MALIDP500_SE_IRQ_GLOBAL,
7491cb3cbe7SLiviu Dudau 				.vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
750ad49f860SLiviu Dudau 			},
751ad49f860SLiviu Dudau 			.dc_irq_map = {
752ad49f860SLiviu Dudau 				.irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
753ad49f860SLiviu Dudau 				.vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
754ad49f860SLiviu Dudau 			},
7556211b486SBrian Starkey 			.pixel_formats = malidp500_de_formats,
7566211b486SBrian Starkey 			.n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
757a228062cSBrian Starkey 			.bus_align_bytes = 8,
758ad49f860SLiviu Dudau 		},
759ad49f860SLiviu Dudau 		.query_hw = malidp500_query_hw,
760ad49f860SLiviu Dudau 		.enter_config_mode = malidp500_enter_config_mode,
761ad49f860SLiviu Dudau 		.leave_config_mode = malidp500_leave_config_mode,
762ad49f860SLiviu Dudau 		.in_config_mode = malidp500_in_config_mode,
763ad49f860SLiviu Dudau 		.set_config_valid = malidp500_set_config_valid,
764ad49f860SLiviu Dudau 		.modeset = malidp500_modeset,
765ad49f860SLiviu Dudau 		.rotmem_required = malidp500_rotmem_required,
76628ce675bSMihail Atanassov 		.se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
767c2e7f82dSMihail Atanassov 		.se_calc_mclk = malidp500_se_calc_mclk,
7681cb3cbe7SLiviu Dudau 		.enable_memwrite = malidp500_enable_memwrite,
7691cb3cbe7SLiviu Dudau 		.disable_memwrite = malidp500_disable_memwrite,
77083d642eeSMihail Atanassov 		.features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
771ad49f860SLiviu Dudau 	},
772ad49f860SLiviu Dudau 	[MALIDP_550] = {
773ad49f860SLiviu Dudau 		.map = {
77402725d31SMihail Atanassov 			.coeffs_base = MALIDP550_COEFFS_BASE,
775ad49f860SLiviu Dudau 			.se_base = MALIDP550_SE_BASE,
776ad49f860SLiviu Dudau 			.dc_base = MALIDP550_DC_BASE,
777ad49f860SLiviu Dudau 			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
778ad49f860SLiviu Dudau 			.features = MALIDP_REGMAP_HAS_CLEARIRQ,
779ad49f860SLiviu Dudau 			.n_layers = ARRAY_SIZE(malidp550_layers),
780ad49f860SLiviu Dudau 			.layers = malidp550_layers,
781ad49f860SLiviu Dudau 			.de_irq_map = {
782ad49f860SLiviu Dudau 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
783ad49f860SLiviu Dudau 					    MALIDP550_DE_IRQ_VSYNC,
784ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DE_IRQ_VSYNC,
785ad49f860SLiviu Dudau 			},
786ad49f860SLiviu Dudau 			.se_irq_map = {
787ad49f860SLiviu Dudau 				.irq_mask = MALIDP550_SE_IRQ_EOW |
788ad49f860SLiviu Dudau 					    MALIDP550_SE_IRQ_AXI_ERR,
789846c87a0SLiviu Dudau 				.vsync_irq = MALIDP550_SE_IRQ_EOW,
790ad49f860SLiviu Dudau 			},
791ad49f860SLiviu Dudau 			.dc_irq_map = {
792846c87a0SLiviu Dudau 				.irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
793846c87a0SLiviu Dudau 					    MALIDP550_DC_IRQ_SE,
794ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
795ad49f860SLiviu Dudau 			},
7966211b486SBrian Starkey 			.pixel_formats = malidp550_de_formats,
7976211b486SBrian Starkey 			.n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
798a228062cSBrian Starkey 			.bus_align_bytes = 8,
799ad49f860SLiviu Dudau 		},
800ad49f860SLiviu Dudau 		.query_hw = malidp550_query_hw,
801ad49f860SLiviu Dudau 		.enter_config_mode = malidp550_enter_config_mode,
802ad49f860SLiviu Dudau 		.leave_config_mode = malidp550_leave_config_mode,
803ad49f860SLiviu Dudau 		.in_config_mode = malidp550_in_config_mode,
804ad49f860SLiviu Dudau 		.set_config_valid = malidp550_set_config_valid,
805ad49f860SLiviu Dudau 		.modeset = malidp550_modeset,
806ad49f860SLiviu Dudau 		.rotmem_required = malidp550_rotmem_required,
80728ce675bSMihail Atanassov 		.se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
808c2e7f82dSMihail Atanassov 		.se_calc_mclk = malidp550_se_calc_mclk,
809846c87a0SLiviu Dudau 		.enable_memwrite = malidp550_enable_memwrite,
810846c87a0SLiviu Dudau 		.disable_memwrite = malidp550_disable_memwrite,
81183d642eeSMihail Atanassov 		.features = 0,
812ad49f860SLiviu Dudau 	},
813ad49f860SLiviu Dudau 	[MALIDP_650] = {
814ad49f860SLiviu Dudau 		.map = {
81502725d31SMihail Atanassov 			.coeffs_base = MALIDP550_COEFFS_BASE,
816ad49f860SLiviu Dudau 			.se_base = MALIDP550_SE_BASE,
817ad49f860SLiviu Dudau 			.dc_base = MALIDP550_DC_BASE,
818ad49f860SLiviu Dudau 			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
819ad49f860SLiviu Dudau 			.features = MALIDP_REGMAP_HAS_CLEARIRQ,
820ad49f860SLiviu Dudau 			.n_layers = ARRAY_SIZE(malidp550_layers),
821ad49f860SLiviu Dudau 			.layers = malidp550_layers,
822ad49f860SLiviu Dudau 			.de_irq_map = {
823ad49f860SLiviu Dudau 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
824ad49f860SLiviu Dudau 					    MALIDP650_DE_IRQ_DRIFT |
825ad49f860SLiviu Dudau 					    MALIDP550_DE_IRQ_VSYNC,
826ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DE_IRQ_VSYNC,
827ad49f860SLiviu Dudau 			},
828ad49f860SLiviu Dudau 			.se_irq_map = {
829ad49f860SLiviu Dudau 				.irq_mask = MALIDP550_SE_IRQ_EOW |
830ad49f860SLiviu Dudau 					    MALIDP550_SE_IRQ_AXI_ERR,
831846c87a0SLiviu Dudau 				.vsync_irq = MALIDP550_SE_IRQ_EOW,
832ad49f860SLiviu Dudau 			},
833ad49f860SLiviu Dudau 			.dc_irq_map = {
834846c87a0SLiviu Dudau 				.irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
835846c87a0SLiviu Dudau 					    MALIDP550_DC_IRQ_SE,
836ad49f860SLiviu Dudau 				.vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
837ad49f860SLiviu Dudau 			},
8386211b486SBrian Starkey 			.pixel_formats = malidp550_de_formats,
8396211b486SBrian Starkey 			.n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
840a228062cSBrian Starkey 			.bus_align_bytes = 16,
841ad49f860SLiviu Dudau 		},
842ad49f860SLiviu Dudau 		.query_hw = malidp650_query_hw,
843ad49f860SLiviu Dudau 		.enter_config_mode = malidp550_enter_config_mode,
844ad49f860SLiviu Dudau 		.leave_config_mode = malidp550_leave_config_mode,
845ad49f860SLiviu Dudau 		.in_config_mode = malidp550_in_config_mode,
846ad49f860SLiviu Dudau 		.set_config_valid = malidp550_set_config_valid,
847ad49f860SLiviu Dudau 		.modeset = malidp550_modeset,
848ad49f860SLiviu Dudau 		.rotmem_required = malidp550_rotmem_required,
84928ce675bSMihail Atanassov 		.se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
850c2e7f82dSMihail Atanassov 		.se_calc_mclk = malidp550_se_calc_mclk,
851846c87a0SLiviu Dudau 		.enable_memwrite = malidp550_enable_memwrite,
852846c87a0SLiviu Dudau 		.disable_memwrite = malidp550_disable_memwrite,
85383d642eeSMihail Atanassov 		.features = 0,
854ad49f860SLiviu Dudau 	},
855ad49f860SLiviu Dudau };
856ad49f860SLiviu Dudau 
857ad49f860SLiviu Dudau u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
858ad49f860SLiviu Dudau 			   u8 layer_id, u32 format)
859ad49f860SLiviu Dudau {
860ad49f860SLiviu Dudau 	unsigned int i;
861ad49f860SLiviu Dudau 
8626211b486SBrian Starkey 	for (i = 0; i < map->n_pixel_formats; i++) {
8636211b486SBrian Starkey 		if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
8646211b486SBrian Starkey 		    (map->pixel_formats[i].format == format))
8656211b486SBrian Starkey 			return map->pixel_formats[i].id;
866ad49f860SLiviu Dudau 	}
867ad49f860SLiviu Dudau 
868ad49f860SLiviu Dudau 	return MALIDP_INVALID_FORMAT_ID;
869ad49f860SLiviu Dudau }
870ad49f860SLiviu Dudau 
871ad49f860SLiviu Dudau static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
872ad49f860SLiviu Dudau {
873ad49f860SLiviu Dudau 	u32 base = malidp_get_block_base(hwdev, block);
874ad49f860SLiviu Dudau 
875a6993b21SLiviu Dudau 	if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
876ad49f860SLiviu Dudau 		malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
877ad49f860SLiviu Dudau 	else
878ad49f860SLiviu Dudau 		malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
879ad49f860SLiviu Dudau }
880ad49f860SLiviu Dudau 
881ad49f860SLiviu Dudau static irqreturn_t malidp_de_irq(int irq, void *arg)
882ad49f860SLiviu Dudau {
883ad49f860SLiviu Dudau 	struct drm_device *drm = arg;
884ad49f860SLiviu Dudau 	struct malidp_drm *malidp = drm->dev_private;
885ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev;
886a6993b21SLiviu Dudau 	struct malidp_hw *hw;
887ad49f860SLiviu Dudau 	const struct malidp_irq_map *de;
888ad49f860SLiviu Dudau 	u32 status, mask, dc_status;
889ad49f860SLiviu Dudau 	irqreturn_t ret = IRQ_NONE;
890ad49f860SLiviu Dudau 
891ad49f860SLiviu Dudau 	hwdev = malidp->dev;
892a6993b21SLiviu Dudau 	hw = hwdev->hw;
893a6993b21SLiviu Dudau 	de = &hw->map.de_irq_map;
894ad49f860SLiviu Dudau 
8950df34a80SLiviu Dudau 	/*
8960df34a80SLiviu Dudau 	 * if we are suspended it is likely that we were invoked because
8970df34a80SLiviu Dudau 	 * we share an interrupt line with some other driver, don't try
8980df34a80SLiviu Dudau 	 * to read the hardware registers
8990df34a80SLiviu Dudau 	 */
9000df34a80SLiviu Dudau 	if (hwdev->pm_suspended)
9010df34a80SLiviu Dudau 		return IRQ_NONE;
9020df34a80SLiviu Dudau 
903ad49f860SLiviu Dudau 	/* first handle the config valid IRQ */
904a6993b21SLiviu Dudau 	dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
905a6993b21SLiviu Dudau 	if (dc_status & hw->map.dc_irq_map.vsync_irq) {
906ad49f860SLiviu Dudau 		malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
907d862b2d6SLiviu Dudau 		/* do we have a page flip event? */
908d862b2d6SLiviu Dudau 		if (malidp->event != NULL) {
909d862b2d6SLiviu Dudau 			spin_lock(&drm->event_lock);
910d862b2d6SLiviu Dudau 			drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
911d862b2d6SLiviu Dudau 			malidp->event = NULL;
912d862b2d6SLiviu Dudau 			spin_unlock(&drm->event_lock);
913d862b2d6SLiviu Dudau 		}
9141cb3cbe7SLiviu Dudau 		atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
915ad49f860SLiviu Dudau 		ret = IRQ_WAKE_THREAD;
916ad49f860SLiviu Dudau 	}
917ad49f860SLiviu Dudau 
918ad49f860SLiviu Dudau 	status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
919ad49f860SLiviu Dudau 	if (!(status & de->irq_mask))
920ad49f860SLiviu Dudau 		return ret;
921ad49f860SLiviu Dudau 
922ad49f860SLiviu Dudau 	mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
923ad49f860SLiviu Dudau 	status &= mask;
924d862b2d6SLiviu Dudau 	if ((status & de->vsync_irq) && malidp->crtc.enabled)
925ad49f860SLiviu Dudau 		drm_crtc_handle_vblank(&malidp->crtc);
926ad49f860SLiviu Dudau 
927ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
928ad49f860SLiviu Dudau 
929ad49f860SLiviu Dudau 	return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
930ad49f860SLiviu Dudau }
931ad49f860SLiviu Dudau 
932ad49f860SLiviu Dudau static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
933ad49f860SLiviu Dudau {
934ad49f860SLiviu Dudau 	struct drm_device *drm = arg;
935ad49f860SLiviu Dudau 	struct malidp_drm *malidp = drm->dev_private;
936ad49f860SLiviu Dudau 
937ad49f860SLiviu Dudau 	wake_up(&malidp->wq);
938ad49f860SLiviu Dudau 
939ad49f860SLiviu Dudau 	return IRQ_HANDLED;
940ad49f860SLiviu Dudau }
941ad49f860SLiviu Dudau 
942ad49f860SLiviu Dudau int malidp_de_irq_init(struct drm_device *drm, int irq)
943ad49f860SLiviu Dudau {
944ad49f860SLiviu Dudau 	struct malidp_drm *malidp = drm->dev_private;
945ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
946ad49f860SLiviu Dudau 	int ret;
947ad49f860SLiviu Dudau 
948ad49f860SLiviu Dudau 	/* ensure interrupts are disabled */
949ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
950ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
951ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
952ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
953ad49f860SLiviu Dudau 
954ad49f860SLiviu Dudau 	ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
955ad49f860SLiviu Dudau 					malidp_de_irq_thread_handler,
956ad49f860SLiviu Dudau 					IRQF_SHARED, "malidp-de", drm);
957ad49f860SLiviu Dudau 	if (ret < 0) {
958ad49f860SLiviu Dudau 		DRM_ERROR("failed to install DE IRQ handler\n");
959ad49f860SLiviu Dudau 		return ret;
960ad49f860SLiviu Dudau 	}
961ad49f860SLiviu Dudau 
962ad49f860SLiviu Dudau 	/* first enable the DC block IRQs */
963ad49f860SLiviu Dudau 	malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
964a6993b21SLiviu Dudau 			     hwdev->hw->map.dc_irq_map.irq_mask);
965ad49f860SLiviu Dudau 
966ad49f860SLiviu Dudau 	/* now enable the DE block IRQs */
967ad49f860SLiviu Dudau 	malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
968a6993b21SLiviu Dudau 			     hwdev->hw->map.de_irq_map.irq_mask);
969ad49f860SLiviu Dudau 
970ad49f860SLiviu Dudau 	return 0;
971ad49f860SLiviu Dudau }
972ad49f860SLiviu Dudau 
973ad49f860SLiviu Dudau void malidp_de_irq_fini(struct drm_device *drm)
974ad49f860SLiviu Dudau {
975ad49f860SLiviu Dudau 	struct malidp_drm *malidp = drm->dev_private;
976ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
977ad49f860SLiviu Dudau 
978ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
979a6993b21SLiviu Dudau 			      hwdev->hw->map.de_irq_map.irq_mask);
980ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
981a6993b21SLiviu Dudau 			      hwdev->hw->map.dc_irq_map.irq_mask);
982ad49f860SLiviu Dudau }
983ad49f860SLiviu Dudau 
984ad49f860SLiviu Dudau static irqreturn_t malidp_se_irq(int irq, void *arg)
985ad49f860SLiviu Dudau {
986ad49f860SLiviu Dudau 	struct drm_device *drm = arg;
987ad49f860SLiviu Dudau 	struct malidp_drm *malidp = drm->dev_private;
988ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
989a6993b21SLiviu Dudau 	struct malidp_hw *hw = hwdev->hw;
990a6993b21SLiviu Dudau 	const struct malidp_irq_map *se = &hw->map.se_irq_map;
991ad49f860SLiviu Dudau 	u32 status, mask;
992ad49f860SLiviu Dudau 
9930df34a80SLiviu Dudau 	/*
9940df34a80SLiviu Dudau 	 * if we are suspended it is likely that we were invoked because
9950df34a80SLiviu Dudau 	 * we share an interrupt line with some other driver, don't try
9960df34a80SLiviu Dudau 	 * to read the hardware registers
9970df34a80SLiviu Dudau 	 */
9980df34a80SLiviu Dudau 	if (hwdev->pm_suspended)
9990df34a80SLiviu Dudau 		return IRQ_NONE;
10000df34a80SLiviu Dudau 
1001a6993b21SLiviu Dudau 	status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1002a6993b21SLiviu Dudau 	if (!(status & se->irq_mask))
1003ad49f860SLiviu Dudau 		return IRQ_NONE;
1004ad49f860SLiviu Dudau 
1005a6993b21SLiviu Dudau 	mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1006a6993b21SLiviu Dudau 	status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1007ad49f860SLiviu Dudau 	status &= mask;
10081cb3cbe7SLiviu Dudau 
10091cb3cbe7SLiviu Dudau 	if (status & se->vsync_irq) {
10101cb3cbe7SLiviu Dudau 		switch (hwdev->mw_state) {
10118cbc5cafSBrian Starkey 		case MW_ONESHOT:
10128cbc5cafSBrian Starkey 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
10138cbc5cafSBrian Starkey 			break;
10141cb3cbe7SLiviu Dudau 		case MW_STOP:
10158cbc5cafSBrian Starkey 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
10161cb3cbe7SLiviu Dudau 			/* disable writeback after stop */
10171cb3cbe7SLiviu Dudau 			hwdev->mw_state = MW_NOT_ENABLED;
10181cb3cbe7SLiviu Dudau 			break;
10190735cfdfSLiviu Dudau 		case MW_RESTART:
10200735cfdfSLiviu Dudau 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
10210735cfdfSLiviu Dudau 			/* fall through to a new start */
10221cb3cbe7SLiviu Dudau 		case MW_START:
10231cb3cbe7SLiviu Dudau 			/* writeback started, need to emulate one-shot mode */
10241cb3cbe7SLiviu Dudau 			hw->disable_memwrite(hwdev);
10251cb3cbe7SLiviu Dudau 			/*
10260735cfdfSLiviu Dudau 			 * only set config_valid HW bit if there is no other update
10270735cfdfSLiviu Dudau 			 * in progress or if we raced ahead of the DE IRQ handler
10280735cfdfSLiviu Dudau 			 * and config_valid flag will not be update until later
10291cb3cbe7SLiviu Dudau 			 */
10300735cfdfSLiviu Dudau 			status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
10310735cfdfSLiviu Dudau 			if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
10320735cfdfSLiviu Dudau 			    (status & hw->map.dc_irq_map.vsync_irq))
10330735cfdfSLiviu Dudau 				hw->set_config_valid(hwdev, 1);
10341cb3cbe7SLiviu Dudau 			break;
10351cb3cbe7SLiviu Dudau 		}
10361cb3cbe7SLiviu Dudau 	}
1037ad49f860SLiviu Dudau 
1038ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1039ad49f860SLiviu Dudau 
1040ad49f860SLiviu Dudau 	return IRQ_HANDLED;
1041ad49f860SLiviu Dudau }
1042ad49f860SLiviu Dudau 
1043ad49f860SLiviu Dudau static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1044ad49f860SLiviu Dudau {
1045ad49f860SLiviu Dudau 	return IRQ_HANDLED;
1046ad49f860SLiviu Dudau }
1047ad49f860SLiviu Dudau 
1048ad49f860SLiviu Dudau int malidp_se_irq_init(struct drm_device *drm, int irq)
1049ad49f860SLiviu Dudau {
1050ad49f860SLiviu Dudau 	struct malidp_drm *malidp = drm->dev_private;
1051ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
1052ad49f860SLiviu Dudau 	int ret;
1053ad49f860SLiviu Dudau 
1054ad49f860SLiviu Dudau 	/* ensure interrupts are disabled */
1055ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1056ad49f860SLiviu Dudau 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1057ad49f860SLiviu Dudau 
1058ad49f860SLiviu Dudau 	ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1059ad49f860SLiviu Dudau 					malidp_se_irq_thread_handler,
1060ad49f860SLiviu Dudau 					IRQF_SHARED, "malidp-se", drm);
1061ad49f860SLiviu Dudau 	if (ret < 0) {
1062ad49f860SLiviu Dudau 		DRM_ERROR("failed to install SE IRQ handler\n");
1063ad49f860SLiviu Dudau 		return ret;
1064ad49f860SLiviu Dudau 	}
1065ad49f860SLiviu Dudau 
10661cb3cbe7SLiviu Dudau 	hwdev->mw_state = MW_NOT_ENABLED;
1067ad49f860SLiviu Dudau 	malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1068a6993b21SLiviu Dudau 			     hwdev->hw->map.se_irq_map.irq_mask);
1069ad49f860SLiviu Dudau 
1070ad49f860SLiviu Dudau 	return 0;
1071ad49f860SLiviu Dudau }
1072ad49f860SLiviu Dudau 
1073ad49f860SLiviu Dudau void malidp_se_irq_fini(struct drm_device *drm)
1074ad49f860SLiviu Dudau {
1075ad49f860SLiviu Dudau 	struct malidp_drm *malidp = drm->dev_private;
1076ad49f860SLiviu Dudau 	struct malidp_hw_device *hwdev = malidp->dev;
1077ad49f860SLiviu Dudau 
1078ad49f860SLiviu Dudau 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1079a6993b21SLiviu Dudau 			      hwdev->hw->map.se_irq_map.irq_mask);
1080ad49f860SLiviu Dudau }
1081