Merge series "regulator: fix deadlock vs memory reclaim" from Michał Mirosław <mirq...
[linux-2.6-microblaze.git] / drivers / gpu / drm / arm / malidp_hw.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
4  * Author: Liviu Dudau <Liviu.Dudau@arm.com>
5  *
6  * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
7  * the difference between various versions of the hardware is being dealt with
8  * in an attempt to provide to the rest of the driver code a unified view
9  */
10
11 #include <linux/clk.h>
12 #include <linux/delay.h>
13 #include <linux/types.h>
14 #include <linux/io.h>
15
16 #include <video/videomode.h>
17 #include <video/display_timing.h>
18
19 #include <drm/drm_fourcc.h>
20 #include <drm/drm_vblank.h>
21 #include <drm/drm_print.h>
22
23 #include "malidp_drv.h"
24 #include "malidp_hw.h"
25 #include "malidp_mw.h"
26
27 enum {
28         MW_NOT_ENABLED = 0,     /* SE writeback not enabled */
29         MW_ONESHOT,             /* SE in one-shot mode for writeback */
30         MW_START,               /* SE started writeback */
31         MW_RESTART,             /* SE will start another writeback after this one */
32         MW_STOP,                /* SE needs to stop after this writeback */
33 };
34
35 static const struct malidp_format_id malidp500_de_formats[] = {
36         /*    fourcc,   layers supporting the format,     internal id  */
37         { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  0 },
38         { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  1 },
39         { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  2 },
40         { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  3 },
41         { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  4 },
42         { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  5 },
43         { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  6 },
44         { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  7 },
45         { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  8 },
46         { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  9 },
47         { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
48         { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
49         { DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
50         { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
51         { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
52         { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
53         { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
54         /* These are supported with AFBC only */
55         { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
56         { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
57         { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
58         { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
59 };
60
61 #define MALIDP_ID(__group, __format) \
62         ((((__group) & 0x7) << 3) | ((__format) & 0x7))
63
64 #define AFBC_YUV_422_FORMAT_ID  MALIDP_ID(5, 1)
65
66 #define MALIDP_COMMON_FORMATS \
67         /*    fourcc,   layers supporting the format,      internal id   */ \
68         { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
69         { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
70         { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
71         { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
72         { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
73         { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
74         { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
75         { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
76         { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
77         { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
78         { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
79         { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
80         { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
81         { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
82         { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
83         { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
84         { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
85         { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
86         /* This is only supported with linear modifier */       \
87         { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
88         /* This is only supported with AFBC modifier */         \
89         { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
90         { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) },    \
91         /* This is only supported with linear modifier */ \
92         { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) },    \
93         { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) },      \
94         /* This is only supported with AFBC modifier */ \
95         { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
96         { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
97         /* This is only supported with linear modifier */ \
98         { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
99         /* This is only supported with AFBC modifier */ \
100         { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
101         { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
102         /* This is only supported with AFBC modifier */ \
103         { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
104         { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
105
106 static const struct malidp_format_id malidp550_de_formats[] = {
107         MALIDP_COMMON_FORMATS,
108 };
109
110 static const struct malidp_format_id malidp650_de_formats[] = {
111         MALIDP_COMMON_FORMATS,
112         { DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)},
113 };
114
115 static const struct malidp_layer malidp500_layers[] = {
116         /* id, base address, fb pointer address base, stride offset,
117          *      yuv2rgb matrix offset, mmu control register offset, rotation_features
118          */
119         { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
120                 MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
121                 MALIDP500_DE_LV_AD_CTRL },
122         { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
123                 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
124                 MALIDP500_DE_LG1_AD_CTRL },
125         { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
126                 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
127                 MALIDP500_DE_LG2_AD_CTRL },
128 };
129
130 static const struct malidp_layer malidp550_layers[] = {
131         /* id, base address, fb pointer address base, stride offset,
132          *      yuv2rgb matrix offset, mmu control register offset, rotation_features
133          */
134         { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
135                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
136                 MALIDP550_DE_LV1_AD_CTRL },
137         { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
138                 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
139                 MALIDP550_DE_LG_AD_CTRL },
140         { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
141                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
142                 MALIDP550_DE_LV2_AD_CTRL },
143         { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
144                 MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
145 };
146
147 static const struct malidp_layer malidp650_layers[] = {
148         /* id, base address, fb pointer address base, stride offset,
149          *      yuv2rgb matrix offset, mmu control register offset,
150          *      rotation_features
151          */
152         { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
153                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
154                 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
155                 MALIDP550_DE_LV1_AD_CTRL },
156         { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
157                 MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
158                 ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
159         { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
160                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
161                 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
162                 MALIDP550_DE_LV2_AD_CTRL },
163         { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
164                 MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
165                 ROTATE_NONE, 0 },
166 };
167
168 const u64 malidp_format_modifiers[] = {
169         /* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
170         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
171         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
172
173         /* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
174         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
175
176         /* All 8 or 10 bit YUV 444 formats. */
177         /* In DP550, 10 bit YUV 420 format also supported */
178         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
179
180         /* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
181         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
182         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
183
184         /* YUV 420, 422 P1 8, 10 bit formats */
185         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
186         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
187
188         /* All formats */
189         DRM_FORMAT_MOD_LINEAR,
190
191         DRM_FORMAT_MOD_INVALID
192 };
193
194 #define SE_N_SCALING_COEFFS     96
195 static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
196         [MALIDP_UPSCALING_COEFFS - 1] = {
197                 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
198                 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
199                 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
200                 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
201                 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
202                 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
203                 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
204                 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
205                 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
206                 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
207                 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
208                 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
209         },
210         [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
211                 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
212                 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
213                 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
214                 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
215                 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
216                 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
217                 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
218                 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
219                 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
220                 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
221                 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
222                 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
223         },
224         [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
225                 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
226                 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
227                 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
228                 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
229                 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
230                 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
231                 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
232                 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
233                 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
234                 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
235                 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
236                 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
237         },
238         [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
239                 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
240                 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
241                 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
242                 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
243                 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
244                 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
245                 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
246                 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
247                 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
248                 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
249                 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
250                 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
251         },
252         [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
253                 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
254                 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
255                 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
256                 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
257                 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
258                 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
259                 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
260                 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
261                 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
262                 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
263                 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
264                 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
265         },
266 };
267
268 #define MALIDP_DE_DEFAULT_PREFETCH_START        5
269
270 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
271 {
272         u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
273         /* bit 4 of the CONFIG_ID register holds the line size multiplier */
274         u8 ln_size_mult = conf & 0x10 ? 2 : 1;
275
276         hwdev->min_line_size = 2;
277         hwdev->max_line_size = SZ_2K * ln_size_mult;
278         hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
279         hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
280
281         return 0;
282 }
283
284 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
285 {
286         u32 status, count = 100;
287
288         malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
289         while (count) {
290                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
291                 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
292                         break;
293                 /*
294                  * entering config mode can take as long as the rendering
295                  * of a full frame, hence the long sleep here
296                  */
297                 usleep_range(1000, 10000);
298                 count--;
299         }
300         WARN(count == 0, "timeout while entering config mode");
301 }
302
303 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
304 {
305         u32 status, count = 100;
306
307         malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
308         malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
309         while (count) {
310                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
311                 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
312                         break;
313                 usleep_range(100, 1000);
314                 count--;
315         }
316         WARN(count == 0, "timeout while leaving config mode");
317 }
318
319 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
320 {
321         u32 status;
322
323         status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
324         if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
325                 return true;
326
327         return false;
328 }
329
330 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
331 {
332         if (value)
333                 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
334         else
335                 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
336 }
337
338 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
339 {
340         u32 val = 0;
341
342         malidp_hw_write(hwdev, hwdev->output_color_depth,
343                 hwdev->hw->map.out_depth_base);
344         malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
345         if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
346                 val |= MALIDP500_HSYNCPOL;
347         if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
348                 val |= MALIDP500_VSYNCPOL;
349         val |= MALIDP_DE_DEFAULT_PREFETCH_START;
350         malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
351
352         /*
353          * Mali-DP500 encodes the background color like this:
354          *    - red   @ MALIDP500_BGND_COLOR[12:0]
355          *    - green @ MALIDP500_BGND_COLOR[27:16]
356          *    - blue  @ (MALIDP500_BGND_COLOR + 4)[12:0]
357          */
358         val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
359               (MALIDP_BGND_COLOR_R & 0xfff);
360         malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
361         malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
362
363         val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
364                 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
365         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
366
367         val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
368                 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
369         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
370
371         val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
372                 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
373         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
374
375         val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
376         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
377
378         if (mode->flags & DISPLAY_FLAGS_INTERLACED)
379                 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
380         else
381                 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
382
383         /*
384          * Program the RQoS register to avoid high resolutions flicker
385          * issue on the LS1028A.
386          */
387         if (hwdev->arqos_value) {
388                 val = hwdev->arqos_value;
389                 malidp_hw_setbits(hwdev, val, MALIDP500_RQOS_QUALITY);
390         }
391 }
392
393 int malidp_format_get_bpp(u32 fmt)
394 {
395         const struct drm_format_info *info = drm_format_info(fmt);
396         int bpp = info->cpp[0] * 8;
397
398         if (bpp == 0) {
399                 switch (fmt) {
400                 case DRM_FORMAT_VUY101010:
401                         bpp = 30;
402                         break;
403                 case DRM_FORMAT_YUV420_10BIT:
404                         bpp = 15;
405                         break;
406                 case DRM_FORMAT_YUV420_8BIT:
407                         bpp = 12;
408                         break;
409                 default:
410                         bpp = 0;
411                 }
412         }
413
414         return bpp;
415 }
416
417 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
418                                      u16 h, u32 fmt, bool has_modifier)
419 {
420         /*
421          * Each layer needs enough rotation memory to fit 8 lines
422          * worth of pixel data. Required size is then:
423          *    size = rotated_width * (bpp / 8) * 8;
424          */
425         int bpp = malidp_format_get_bpp(fmt);
426
427         return w * bpp;
428 }
429
430 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
431                                            u32 direction,
432                                            u16 addr,
433                                            u8 coeffs_id)
434 {
435         int i;
436         u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
437
438         malidp_hw_write(hwdev,
439                         direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
440                         scaling_control + MALIDP_SE_COEFFTAB_ADDR);
441         for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
442                 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
443                                 dp500_se_scaling_coeffs[coeffs_id][i]),
444                                 scaling_control + MALIDP_SE_COEFFTAB_DATA);
445 }
446
447 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
448                                            struct malidp_se_config *se_config,
449                                            struct malidp_se_config *old_config)
450 {
451         /* Get array indices into dp500_se_scaling_coeffs. */
452         u8 h = (u8)se_config->hcoeff - 1;
453         u8 v = (u8)se_config->vcoeff - 1;
454
455         if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
456                     v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
457                 return -EINVAL;
458
459         if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
460                          se_config->vcoeff != old_config->vcoeff)) {
461                 malidp500_se_write_pp_coefftab(hwdev,
462                                                (MALIDP_SE_V_COEFFTAB |
463                                                 MALIDP_SE_H_COEFFTAB),
464                                                0, v);
465         } else {
466                 if (se_config->vcoeff != old_config->vcoeff)
467                         malidp500_se_write_pp_coefftab(hwdev,
468                                                        MALIDP_SE_V_COEFFTAB,
469                                                        0, v);
470                 if (se_config->hcoeff != old_config->hcoeff)
471                         malidp500_se_write_pp_coefftab(hwdev,
472                                                        MALIDP_SE_H_COEFFTAB,
473                                                        0, h);
474         }
475
476         return 0;
477 }
478
479 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
480                                    struct malidp_se_config *se_config,
481                                    struct videomode *vm)
482 {
483         unsigned long mclk;
484         unsigned long pxlclk = vm->pixelclock; /* Hz */
485         unsigned long htotal = vm->hactive + vm->hfront_porch +
486                                vm->hback_porch + vm->hsync_len;
487         unsigned long input_size = se_config->input_w * se_config->input_h;
488         unsigned long a = 10;
489         long ret;
490
491         /*
492          * mclk = max(a, 1.5) * pxlclk
493          *
494          * To avoid float calculaiton, using 15 instead of 1.5 and div by
495          * 10 to get mclk.
496          */
497         if (se_config->scale_enable) {
498                 a = 15 * input_size / (htotal * se_config->output_h);
499                 if (a < 15)
500                         a = 15;
501         }
502         mclk = a * pxlclk / 10;
503         ret = clk_get_rate(hwdev->mclk);
504         if (ret < mclk) {
505                 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
506                                  mclk / 1000);
507                 return -EINVAL;
508         }
509         return ret;
510 }
511
512 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
513                                      dma_addr_t *addrs, s32 *pitches,
514                                      int num_planes, u16 w, u16 h, u32 fmt_id,
515                                      const s16 *rgb2yuv_coeffs)
516 {
517         u32 base = MALIDP500_SE_MEMWRITE_BASE;
518         u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
519
520         /* enable the scaling engine block */
521         malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
522
523         /* restart the writeback if already enabled */
524         if (hwdev->mw_state != MW_NOT_ENABLED)
525                 hwdev->mw_state = MW_RESTART;
526         else
527                 hwdev->mw_state = MW_START;
528
529         malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
530         switch (num_planes) {
531         case 2:
532                 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
533                 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
534                 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
535                 /* fall through */
536         case 1:
537                 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
538                 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
539                 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
540                 break;
541         default:
542                 WARN(1, "Invalid number of planes");
543         }
544
545         malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
546                         MALIDP500_SE_MEMWRITE_OUT_SIZE);
547
548         if (rgb2yuv_coeffs) {
549                 int i;
550
551                 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
552                         malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
553                                         MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
554                 }
555         }
556
557         malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
558
559         return 0;
560 }
561
562 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
563 {
564         u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
565
566         if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
567                 hwdev->mw_state = MW_STOP;
568         malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
569         malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
570 }
571
572 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
573 {
574         u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
575         u8 ln_size = (conf >> 4) & 0x3, rsize;
576
577         hwdev->min_line_size = 2;
578
579         switch (ln_size) {
580         case 0:
581                 hwdev->max_line_size = SZ_2K;
582                 /* two banks of 64KB for rotation memory */
583                 rsize = 64;
584                 break;
585         case 1:
586                 hwdev->max_line_size = SZ_4K;
587                 /* two banks of 128KB for rotation memory */
588                 rsize = 128;
589                 break;
590         case 2:
591                 hwdev->max_line_size = 1280;
592                 /* two banks of 40KB for rotation memory */
593                 rsize = 40;
594                 break;
595         case 3:
596                 /* reserved value */
597                 hwdev->max_line_size = 0;
598                 return -EINVAL;
599         }
600
601         hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
602         return 0;
603 }
604
605 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
606 {
607         u32 status, count = 100;
608
609         malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
610         while (count) {
611                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
612                 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
613                         break;
614                 /*
615                  * entering config mode can take as long as the rendering
616                  * of a full frame, hence the long sleep here
617                  */
618                 usleep_range(1000, 10000);
619                 count--;
620         }
621         WARN(count == 0, "timeout while entering config mode");
622 }
623
624 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
625 {
626         u32 status, count = 100;
627
628         malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
629         malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
630         while (count) {
631                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
632                 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
633                         break;
634                 usleep_range(100, 1000);
635                 count--;
636         }
637         WARN(count == 0, "timeout while leaving config mode");
638 }
639
640 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
641 {
642         u32 status;
643
644         status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
645         if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
646                 return true;
647
648         return false;
649 }
650
651 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
652 {
653         if (value)
654                 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
655         else
656                 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
657 }
658
659 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
660 {
661         u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
662
663         malidp_hw_write(hwdev, hwdev->output_color_depth,
664                 hwdev->hw->map.out_depth_base);
665         malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
666         /*
667          * Mali-DP550 and Mali-DP650 encode the background color like this:
668          *   - red   @ MALIDP550_DE_BGND_COLOR[23:16]
669          *   - green @ MALIDP550_DE_BGND_COLOR[15:8]
670          *   - blue  @ MALIDP550_DE_BGND_COLOR[7:0]
671          *
672          * We need to truncate the least significant 4 bits from the default
673          * MALIDP_BGND_COLOR_x values
674          */
675         val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
676               (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
677               ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
678         malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
679
680         val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
681                 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
682         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
683
684         val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
685                 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
686         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
687
688         val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
689                 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
690         if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
691                 val |= MALIDP550_HSYNCPOL;
692         if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
693                 val |= MALIDP550_VSYNCPOL;
694         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
695
696         val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
697         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
698
699         if (mode->flags & DISPLAY_FLAGS_INTERLACED)
700                 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
701         else
702                 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
703 }
704
705 static int malidpx50_get_bytes_per_column(u32 fmt)
706 {
707         u32 bytes_per_column;
708
709         switch (fmt) {
710         /* 8 lines at 4 bytes per pixel */
711         case DRM_FORMAT_ARGB2101010:
712         case DRM_FORMAT_ABGR2101010:
713         case DRM_FORMAT_RGBA1010102:
714         case DRM_FORMAT_BGRA1010102:
715         case DRM_FORMAT_ARGB8888:
716         case DRM_FORMAT_ABGR8888:
717         case DRM_FORMAT_RGBA8888:
718         case DRM_FORMAT_BGRA8888:
719         case DRM_FORMAT_XRGB8888:
720         case DRM_FORMAT_XBGR8888:
721         case DRM_FORMAT_RGBX8888:
722         case DRM_FORMAT_BGRX8888:
723         case DRM_FORMAT_RGB888:
724         case DRM_FORMAT_BGR888:
725         /* 16 lines at 2 bytes per pixel */
726         case DRM_FORMAT_RGBA5551:
727         case DRM_FORMAT_ABGR1555:
728         case DRM_FORMAT_RGB565:
729         case DRM_FORMAT_BGR565:
730         case DRM_FORMAT_UYVY:
731         case DRM_FORMAT_YUYV:
732         case DRM_FORMAT_X0L0:
733                 bytes_per_column = 32;
734                 break;
735         /* 16 lines at 1.5 bytes per pixel */
736         case DRM_FORMAT_NV12:
737         case DRM_FORMAT_YUV420:
738         /* 8 lines at 3 bytes per pixel */
739         case DRM_FORMAT_VUY888:
740         /* 16 lines at 12 bits per pixel */
741         case DRM_FORMAT_YUV420_8BIT:
742         /* 8 lines at 3 bytes per pixel */
743         case DRM_FORMAT_P010:
744                 bytes_per_column = 24;
745                 break;
746         /* 8 lines at 30 bits per pixel */
747         case DRM_FORMAT_VUY101010:
748         /* 16 lines at 15 bits per pixel */
749         case DRM_FORMAT_YUV420_10BIT:
750                 bytes_per_column = 30;
751                 break;
752         default:
753                 return -EINVAL;
754         }
755
756         return bytes_per_column;
757 }
758
759 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
760                                      u16 h, u32 fmt, bool has_modifier)
761 {
762         int bytes_per_column = 0;
763
764         switch (fmt) {
765         /* 8 lines at 15 bits per pixel */
766         case DRM_FORMAT_YUV420_10BIT:
767                 bytes_per_column = 15;
768                 break;
769         /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
770         case DRM_FORMAT_X0L2:
771                 if (has_modifier)
772                         bytes_per_column = 8;
773                 else
774                         return -EINVAL;
775                 break;
776         default:
777                 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
778         }
779
780         if (bytes_per_column == -EINVAL)
781                 return bytes_per_column;
782
783         return w * bytes_per_column;
784 }
785
786 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
787                                      u16 h, u32 fmt, bool has_modifier)
788 {
789         int bytes_per_column = 0;
790
791         switch (fmt) {
792         /* 16 lines at 2 bytes per pixel */
793         case DRM_FORMAT_X0L2:
794                 bytes_per_column = 32;
795                 break;
796         default:
797                 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
798         }
799
800         if (bytes_per_column == -EINVAL)
801                 return bytes_per_column;
802
803         return w * bytes_per_column;
804 }
805
806 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
807                                            struct malidp_se_config *se_config,
808                                            struct malidp_se_config *old_config)
809 {
810         u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
811                    MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
812         u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
813                         MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
814
815         malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
816         malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
817         return 0;
818 }
819
820 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
821                                    struct malidp_se_config *se_config,
822                                    struct videomode *vm)
823 {
824         unsigned long mclk;
825         unsigned long pxlclk = vm->pixelclock;
826         unsigned long htotal = vm->hactive + vm->hfront_porch +
827                                vm->hback_porch + vm->hsync_len;
828         unsigned long numerator = 1, denominator = 1;
829         long ret;
830
831         if (se_config->scale_enable) {
832                 numerator = max(se_config->input_w, se_config->output_w) *
833                             se_config->input_h;
834                 numerator += se_config->output_w *
835                              (se_config->output_h -
836                               min(se_config->input_h, se_config->output_h));
837                 denominator = (htotal - 2) * se_config->output_h;
838         }
839
840         /* mclk can't be slower than pxlclk. */
841         if (numerator < denominator)
842                 numerator = denominator = 1;
843         mclk = (pxlclk * numerator) / denominator;
844         ret = clk_get_rate(hwdev->mclk);
845         if (ret < mclk) {
846                 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
847                                  mclk / 1000);
848                 return -EINVAL;
849         }
850         return ret;
851 }
852
853 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
854                                      dma_addr_t *addrs, s32 *pitches,
855                                      int num_planes, u16 w, u16 h, u32 fmt_id,
856                                      const s16 *rgb2yuv_coeffs)
857 {
858         u32 base = MALIDP550_SE_MEMWRITE_BASE;
859         u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
860
861         /* enable the scaling engine block */
862         malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
863
864         hwdev->mw_state = MW_ONESHOT;
865
866         malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
867         switch (num_planes) {
868         case 2:
869                 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
870                 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
871                 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
872                 /* fall through */
873         case 1:
874                 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
875                 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
876                 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
877                 break;
878         default:
879                 WARN(1, "Invalid number of planes");
880         }
881
882         malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
883                         MALIDP550_SE_MEMWRITE_OUT_SIZE);
884         malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
885                           MALIDP550_SE_CONTROL);
886
887         if (rgb2yuv_coeffs) {
888                 int i;
889
890                 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
891                         malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
892                                         MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
893                 }
894         }
895
896         return 0;
897 }
898
899 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
900 {
901         u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
902
903         malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
904                             MALIDP550_SE_CONTROL);
905         malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
906 }
907
908 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
909 {
910         u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
911         u8 ln_size = (conf >> 4) & 0x3, rsize;
912
913         hwdev->min_line_size = 4;
914
915         switch (ln_size) {
916         case 0:
917         case 2:
918                 /* reserved values */
919                 hwdev->max_line_size = 0;
920                 return -EINVAL;
921         case 1:
922                 hwdev->max_line_size = SZ_4K;
923                 /* two banks of 128KB for rotation memory */
924                 rsize = 128;
925                 break;
926         case 3:
927                 hwdev->max_line_size = 2560;
928                 /* two banks of 80KB for rotation memory */
929                 rsize = 80;
930         }
931
932         hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
933         return 0;
934 }
935
936 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
937         [MALIDP_500] = {
938                 .map = {
939                         .coeffs_base = MALIDP500_COEFFS_BASE,
940                         .se_base = MALIDP500_SE_BASE,
941                         .dc_base = MALIDP500_DC_BASE,
942                         .out_depth_base = MALIDP500_OUTPUT_DEPTH,
943                         .features = 0,  /* no CLEARIRQ register */
944                         .n_layers = ARRAY_SIZE(malidp500_layers),
945                         .layers = malidp500_layers,
946                         .de_irq_map = {
947                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
948                                             MALIDP500_DE_IRQ_AXI_ERR |
949                                             MALIDP500_DE_IRQ_VSYNC |
950                                             MALIDP500_DE_IRQ_GLOBAL,
951                                 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
952                                 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
953                                             MALIDP500_DE_IRQ_AXI_ERR |
954                                             MALIDP500_DE_IRQ_SATURATION,
955                         },
956                         .se_irq_map = {
957                                 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
958                                             MALIDP500_SE_IRQ_CONF_VALID |
959                                             MALIDP500_SE_IRQ_GLOBAL,
960                                 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
961                                 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
962                                             MALIDP500_SE_IRQ_AXI_ERROR |
963                                             MALIDP500_SE_IRQ_OVERRUN,
964                         },
965                         .dc_irq_map = {
966                                 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
967                                 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
968                         },
969                         .pixel_formats = malidp500_de_formats,
970                         .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
971                         .bus_align_bytes = 8,
972                 },
973                 .query_hw = malidp500_query_hw,
974                 .enter_config_mode = malidp500_enter_config_mode,
975                 .leave_config_mode = malidp500_leave_config_mode,
976                 .in_config_mode = malidp500_in_config_mode,
977                 .set_config_valid = malidp500_set_config_valid,
978                 .modeset = malidp500_modeset,
979                 .rotmem_required = malidp500_rotmem_required,
980                 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
981                 .se_calc_mclk = malidp500_se_calc_mclk,
982                 .enable_memwrite = malidp500_enable_memwrite,
983                 .disable_memwrite = malidp500_disable_memwrite,
984                 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
985         },
986         [MALIDP_550] = {
987                 .map = {
988                         .coeffs_base = MALIDP550_COEFFS_BASE,
989                         .se_base = MALIDP550_SE_BASE,
990                         .dc_base = MALIDP550_DC_BASE,
991                         .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
992                         .features = MALIDP_REGMAP_HAS_CLEARIRQ |
993                                     MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
994                                     MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
995                                     MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
996                         .n_layers = ARRAY_SIZE(malidp550_layers),
997                         .layers = malidp550_layers,
998                         .de_irq_map = {
999                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1000                                             MALIDP550_DE_IRQ_VSYNC,
1001                                 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1002                                 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1003                                             MALIDP550_DE_IRQ_SATURATION |
1004                                             MALIDP550_DE_IRQ_AXI_ERR,
1005                         },
1006                         .se_irq_map = {
1007                                 .irq_mask = MALIDP550_SE_IRQ_EOW,
1008                                 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1009                                 .err_mask  = MALIDP550_SE_IRQ_AXI_ERR |
1010                                              MALIDP550_SE_IRQ_OVR |
1011                                              MALIDP550_SE_IRQ_IBSY,
1012                         },
1013                         .dc_irq_map = {
1014                                 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1015                                             MALIDP550_DC_IRQ_SE,
1016                                 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1017                         },
1018                         .pixel_formats = malidp550_de_formats,
1019                         .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1020                         .bus_align_bytes = 8,
1021                 },
1022                 .query_hw = malidp550_query_hw,
1023                 .enter_config_mode = malidp550_enter_config_mode,
1024                 .leave_config_mode = malidp550_leave_config_mode,
1025                 .in_config_mode = malidp550_in_config_mode,
1026                 .set_config_valid = malidp550_set_config_valid,
1027                 .modeset = malidp550_modeset,
1028                 .rotmem_required = malidp550_rotmem_required,
1029                 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1030                 .se_calc_mclk = malidp550_se_calc_mclk,
1031                 .enable_memwrite = malidp550_enable_memwrite,
1032                 .disable_memwrite = malidp550_disable_memwrite,
1033                 .features = 0,
1034         },
1035         [MALIDP_650] = {
1036                 .map = {
1037                         .coeffs_base = MALIDP550_COEFFS_BASE,
1038                         .se_base = MALIDP550_SE_BASE,
1039                         .dc_base = MALIDP550_DC_BASE,
1040                         .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
1041                         .features = MALIDP_REGMAP_HAS_CLEARIRQ |
1042                                     MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
1043                                     MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
1044                         .n_layers = ARRAY_SIZE(malidp650_layers),
1045                         .layers = malidp650_layers,
1046                         .de_irq_map = {
1047                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1048                                             MALIDP650_DE_IRQ_DRIFT |
1049                                             MALIDP550_DE_IRQ_VSYNC,
1050                                 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1051                                 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1052                                             MALIDP650_DE_IRQ_DRIFT |
1053                                             MALIDP550_DE_IRQ_SATURATION |
1054                                             MALIDP550_DE_IRQ_AXI_ERR |
1055                                             MALIDP650_DE_IRQ_ACEV1 |
1056                                             MALIDP650_DE_IRQ_ACEV2 |
1057                                             MALIDP650_DE_IRQ_ACEG |
1058                                             MALIDP650_DE_IRQ_AXIEP,
1059                         },
1060                         .se_irq_map = {
1061                                 .irq_mask = MALIDP550_SE_IRQ_EOW,
1062                                 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1063                                 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1064                                             MALIDP550_SE_IRQ_OVR |
1065                                             MALIDP550_SE_IRQ_IBSY,
1066                         },
1067                         .dc_irq_map = {
1068                                 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1069                                             MALIDP550_DC_IRQ_SE,
1070                                 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1071                         },
1072                         .pixel_formats = malidp650_de_formats,
1073                         .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1074                         .bus_align_bytes = 16,
1075                 },
1076                 .query_hw = malidp650_query_hw,
1077                 .enter_config_mode = malidp550_enter_config_mode,
1078                 .leave_config_mode = malidp550_leave_config_mode,
1079                 .in_config_mode = malidp550_in_config_mode,
1080                 .set_config_valid = malidp550_set_config_valid,
1081                 .modeset = malidp550_modeset,
1082                 .rotmem_required = malidp650_rotmem_required,
1083                 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1084                 .se_calc_mclk = malidp550_se_calc_mclk,
1085                 .enable_memwrite = malidp550_enable_memwrite,
1086                 .disable_memwrite = malidp550_disable_memwrite,
1087                 .features = 0,
1088         },
1089 };
1090
1091 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
1092                            u8 layer_id, u32 format, bool has_modifier)
1093 {
1094         unsigned int i;
1095
1096         for (i = 0; i < map->n_pixel_formats; i++) {
1097                 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
1098                     (map->pixel_formats[i].format == format)) {
1099                         /*
1100                          * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1101                          * is supported by a different h/w format id than
1102                          * DRM_FORMAT_YUYV (only).
1103                          */
1104                         if (format == DRM_FORMAT_YUYV &&
1105                             (has_modifier) &&
1106                             (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
1107                                 return AFBC_YUV_422_FORMAT_ID;
1108                         else
1109                                 return map->pixel_formats[i].id;
1110                 }
1111         }
1112
1113         return MALIDP_INVALID_FORMAT_ID;
1114 }
1115
1116 bool malidp_hw_format_is_linear_only(u32 format)
1117 {
1118         switch (format) {
1119         case DRM_FORMAT_ARGB2101010:
1120         case DRM_FORMAT_RGBA1010102:
1121         case DRM_FORMAT_BGRA1010102:
1122         case DRM_FORMAT_ARGB8888:
1123         case DRM_FORMAT_RGBA8888:
1124         case DRM_FORMAT_BGRA8888:
1125         case DRM_FORMAT_XBGR8888:
1126         case DRM_FORMAT_XRGB8888:
1127         case DRM_FORMAT_RGBX8888:
1128         case DRM_FORMAT_BGRX8888:
1129         case DRM_FORMAT_RGB888:
1130         case DRM_FORMAT_RGB565:
1131         case DRM_FORMAT_ARGB1555:
1132         case DRM_FORMAT_RGBA5551:
1133         case DRM_FORMAT_BGRA5551:
1134         case DRM_FORMAT_UYVY:
1135         case DRM_FORMAT_XYUV8888:
1136         case DRM_FORMAT_XVYU2101010:
1137         case DRM_FORMAT_X0L2:
1138         case DRM_FORMAT_X0L0:
1139                 return true;
1140         default:
1141                 return false;
1142         }
1143 }
1144
1145 bool malidp_hw_format_is_afbc_only(u32 format)
1146 {
1147         switch (format) {
1148         case DRM_FORMAT_VUY888:
1149         case DRM_FORMAT_VUY101010:
1150         case DRM_FORMAT_YUV420_8BIT:
1151         case DRM_FORMAT_YUV420_10BIT:
1152                 return true;
1153         default:
1154                 return false;
1155         }
1156 }
1157
1158 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1159 {
1160         u32 base = malidp_get_block_base(hwdev, block);
1161
1162         if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1163                 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1164         else
1165                 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1166 }
1167
1168 static irqreturn_t malidp_de_irq(int irq, void *arg)
1169 {
1170         struct drm_device *drm = arg;
1171         struct malidp_drm *malidp = drm->dev_private;
1172         struct malidp_hw_device *hwdev;
1173         struct malidp_hw *hw;
1174         const struct malidp_irq_map *de;
1175         u32 status, mask, dc_status;
1176         irqreturn_t ret = IRQ_NONE;
1177
1178         hwdev = malidp->dev;
1179         hw = hwdev->hw;
1180         de = &hw->map.de_irq_map;
1181
1182         /*
1183          * if we are suspended it is likely that we were invoked because
1184          * we share an interrupt line with some other driver, don't try
1185          * to read the hardware registers
1186          */
1187         if (hwdev->pm_suspended)
1188                 return IRQ_NONE;
1189
1190         /* first handle the config valid IRQ */
1191         dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1192         if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1193                 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1194                 /* do we have a page flip event? */
1195                 if (malidp->event != NULL) {
1196                         spin_lock(&drm->event_lock);
1197                         drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1198                         malidp->event = NULL;
1199                         spin_unlock(&drm->event_lock);
1200                 }
1201                 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1202                 ret = IRQ_WAKE_THREAD;
1203         }
1204
1205         status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1206         if (!(status & de->irq_mask))
1207                 return ret;
1208
1209         mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1210         /* keep the status of the enabled interrupts, plus the error bits */
1211         status &= (mask | de->err_mask);
1212         if ((status & de->vsync_irq) && malidp->crtc.enabled)
1213                 drm_crtc_handle_vblank(&malidp->crtc);
1214
1215 #ifdef CONFIG_DEBUG_FS
1216         if (status & de->err_mask) {
1217                 malidp_error(malidp, &malidp->de_errors, status,
1218                              drm_crtc_vblank_count(&malidp->crtc));
1219         }
1220 #endif
1221         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1222
1223         return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1224 }
1225
1226 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1227 {
1228         struct drm_device *drm = arg;
1229         struct malidp_drm *malidp = drm->dev_private;
1230
1231         wake_up(&malidp->wq);
1232
1233         return IRQ_HANDLED;
1234 }
1235
1236 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1237 {
1238         /* ensure interrupts are disabled */
1239         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1240         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1241         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1242         malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1243
1244         /* first enable the DC block IRQs */
1245         malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1246                              hwdev->hw->map.dc_irq_map.irq_mask);
1247
1248         /* now enable the DE block IRQs */
1249         malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1250                              hwdev->hw->map.de_irq_map.irq_mask);
1251 }
1252
1253 int malidp_de_irq_init(struct drm_device *drm, int irq)
1254 {
1255         struct malidp_drm *malidp = drm->dev_private;
1256         struct malidp_hw_device *hwdev = malidp->dev;
1257         int ret;
1258
1259         /* ensure interrupts are disabled */
1260         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1261         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1262         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1263         malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1264
1265         ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1266                                         malidp_de_irq_thread_handler,
1267                                         IRQF_SHARED, "malidp-de", drm);
1268         if (ret < 0) {
1269                 DRM_ERROR("failed to install DE IRQ handler\n");
1270                 return ret;
1271         }
1272
1273         malidp_de_irq_hw_init(hwdev);
1274
1275         return 0;
1276 }
1277
1278 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1279 {
1280         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1281                               hwdev->hw->map.de_irq_map.irq_mask);
1282         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1283                               hwdev->hw->map.dc_irq_map.irq_mask);
1284 }
1285
1286 static irqreturn_t malidp_se_irq(int irq, void *arg)
1287 {
1288         struct drm_device *drm = arg;
1289         struct malidp_drm *malidp = drm->dev_private;
1290         struct malidp_hw_device *hwdev = malidp->dev;
1291         struct malidp_hw *hw = hwdev->hw;
1292         const struct malidp_irq_map *se = &hw->map.se_irq_map;
1293         u32 status, mask;
1294
1295         /*
1296          * if we are suspended it is likely that we were invoked because
1297          * we share an interrupt line with some other driver, don't try
1298          * to read the hardware registers
1299          */
1300         if (hwdev->pm_suspended)
1301                 return IRQ_NONE;
1302
1303         status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1304         if (!(status & (se->irq_mask | se->err_mask)))
1305                 return IRQ_NONE;
1306
1307 #ifdef CONFIG_DEBUG_FS
1308         if (status & se->err_mask)
1309                 malidp_error(malidp, &malidp->se_errors, status,
1310                              drm_crtc_vblank_count(&malidp->crtc));
1311 #endif
1312         mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1313         status &= mask;
1314
1315         if (status & se->vsync_irq) {
1316                 switch (hwdev->mw_state) {
1317                 case MW_ONESHOT:
1318                         drm_writeback_signal_completion(&malidp->mw_connector, 0);
1319                         break;
1320                 case MW_STOP:
1321                         drm_writeback_signal_completion(&malidp->mw_connector, 0);
1322                         /* disable writeback after stop */
1323                         hwdev->mw_state = MW_NOT_ENABLED;
1324                         break;
1325                 case MW_RESTART:
1326                         drm_writeback_signal_completion(&malidp->mw_connector, 0);
1327                         /* fall through - to a new start */
1328                 case MW_START:
1329                         /* writeback started, need to emulate one-shot mode */
1330                         hw->disable_memwrite(hwdev);
1331                         /*
1332                          * only set config_valid HW bit if there is no other update
1333                          * in progress or if we raced ahead of the DE IRQ handler
1334                          * and config_valid flag will not be update until later
1335                          */
1336                         status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1337                         if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1338                             (status & hw->map.dc_irq_map.vsync_irq))
1339                                 hw->set_config_valid(hwdev, 1);
1340                         break;
1341                 }
1342         }
1343
1344         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1345
1346         return IRQ_HANDLED;
1347 }
1348
1349 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1350 {
1351         /* ensure interrupts are disabled */
1352         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1353         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1354
1355         malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1356                              hwdev->hw->map.se_irq_map.irq_mask);
1357 }
1358
1359 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1360 {
1361         return IRQ_HANDLED;
1362 }
1363
1364 int malidp_se_irq_init(struct drm_device *drm, int irq)
1365 {
1366         struct malidp_drm *malidp = drm->dev_private;
1367         struct malidp_hw_device *hwdev = malidp->dev;
1368         int ret;
1369
1370         /* ensure interrupts are disabled */
1371         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1372         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1373
1374         ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1375                                         malidp_se_irq_thread_handler,
1376                                         IRQF_SHARED, "malidp-se", drm);
1377         if (ret < 0) {
1378                 DRM_ERROR("failed to install SE IRQ handler\n");
1379                 return ret;
1380         }
1381
1382         hwdev->mw_state = MW_NOT_ENABLED;
1383         malidp_se_irq_hw_init(hwdev);
1384
1385         return 0;
1386 }
1387
1388 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1389 {
1390         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1391                               hwdev->hw->map.se_irq_map.irq_mask);
1392 }