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