]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - drivers/gpu/drm/arm/malidp_hw.c
Merge branch 'i2c/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
[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 const struct drm_format_info *info = drm_format_info(fmt);
382 int bpp = info->cpp[0] * 8;
383
384 if (bpp == 0) {
385 switch (fmt) {
386 case DRM_FORMAT_VUY101010:
387 bpp = 30;
388 case DRM_FORMAT_YUV420_10BIT:
389 bpp = 15;
390 break;
391 case DRM_FORMAT_YUV420_8BIT:
392 bpp = 12;
393 break;
394 default:
395 bpp = 0;
396 }
397 }
398
399 return bpp;
400 }
401
402 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
403 u16 h, u32 fmt, bool has_modifier)
404 {
405 /*
406 * Each layer needs enough rotation memory to fit 8 lines
407 * worth of pixel data. Required size is then:
408 * size = rotated_width * (bpp / 8) * 8;
409 */
410 int bpp = malidp_format_get_bpp(fmt);
411
412 return w * bpp;
413 }
414
415 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
416 u32 direction,
417 u16 addr,
418 u8 coeffs_id)
419 {
420 int i;
421 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
422
423 malidp_hw_write(hwdev,
424 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
425 scaling_control + MALIDP_SE_COEFFTAB_ADDR);
426 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
427 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
428 dp500_se_scaling_coeffs[coeffs_id][i]),
429 scaling_control + MALIDP_SE_COEFFTAB_DATA);
430 }
431
432 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
433 struct malidp_se_config *se_config,
434 struct malidp_se_config *old_config)
435 {
436 /* Get array indices into dp500_se_scaling_coeffs. */
437 u8 h = (u8)se_config->hcoeff - 1;
438 u8 v = (u8)se_config->vcoeff - 1;
439
440 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
441 v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
442 return -EINVAL;
443
444 if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
445 se_config->vcoeff != old_config->vcoeff)) {
446 malidp500_se_write_pp_coefftab(hwdev,
447 (MALIDP_SE_V_COEFFTAB |
448 MALIDP_SE_H_COEFFTAB),
449 0, v);
450 } else {
451 if (se_config->vcoeff != old_config->vcoeff)
452 malidp500_se_write_pp_coefftab(hwdev,
453 MALIDP_SE_V_COEFFTAB,
454 0, v);
455 if (se_config->hcoeff != old_config->hcoeff)
456 malidp500_se_write_pp_coefftab(hwdev,
457 MALIDP_SE_H_COEFFTAB,
458 0, h);
459 }
460
461 return 0;
462 }
463
464 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
465 struct malidp_se_config *se_config,
466 struct videomode *vm)
467 {
468 unsigned long mclk;
469 unsigned long pxlclk = vm->pixelclock; /* Hz */
470 unsigned long htotal = vm->hactive + vm->hfront_porch +
471 vm->hback_porch + vm->hsync_len;
472 unsigned long input_size = se_config->input_w * se_config->input_h;
473 unsigned long a = 10;
474 long ret;
475
476 /*
477 * mclk = max(a, 1.5) * pxlclk
478 *
479 * To avoid float calculaiton, using 15 instead of 1.5 and div by
480 * 10 to get mclk.
481 */
482 if (se_config->scale_enable) {
483 a = 15 * input_size / (htotal * se_config->output_h);
484 if (a < 15)
485 a = 15;
486 }
487 mclk = a * pxlclk / 10;
488 ret = clk_get_rate(hwdev->mclk);
489 if (ret < mclk) {
490 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
491 mclk / 1000);
492 return -EINVAL;
493 }
494 return ret;
495 }
496
497 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
498 dma_addr_t *addrs, s32 *pitches,
499 int num_planes, u16 w, u16 h, u32 fmt_id,
500 const s16 *rgb2yuv_coeffs)
501 {
502 u32 base = MALIDP500_SE_MEMWRITE_BASE;
503 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
504
505 /* enable the scaling engine block */
506 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
507
508 /* restart the writeback if already enabled */
509 if (hwdev->mw_state != MW_NOT_ENABLED)
510 hwdev->mw_state = MW_RESTART;
511 else
512 hwdev->mw_state = MW_START;
513
514 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
515 switch (num_planes) {
516 case 2:
517 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
518 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
519 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
520 /* fall through */
521 case 1:
522 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
523 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
524 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
525 break;
526 default:
527 WARN(1, "Invalid number of planes");
528 }
529
530 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
531 MALIDP500_SE_MEMWRITE_OUT_SIZE);
532
533 if (rgb2yuv_coeffs) {
534 int i;
535
536 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
537 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
538 MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
539 }
540 }
541
542 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
543
544 return 0;
545 }
546
547 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
548 {
549 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
550
551 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
552 hwdev->mw_state = MW_STOP;
553 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
554 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
555 }
556
557 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
558 {
559 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
560 u8 ln_size = (conf >> 4) & 0x3, rsize;
561
562 hwdev->min_line_size = 2;
563
564 switch (ln_size) {
565 case 0:
566 hwdev->max_line_size = SZ_2K;
567 /* two banks of 64KB for rotation memory */
568 rsize = 64;
569 break;
570 case 1:
571 hwdev->max_line_size = SZ_4K;
572 /* two banks of 128KB for rotation memory */
573 rsize = 128;
574 break;
575 case 2:
576 hwdev->max_line_size = 1280;
577 /* two banks of 40KB for rotation memory */
578 rsize = 40;
579 break;
580 case 3:
581 /* reserved value */
582 hwdev->max_line_size = 0;
583 return -EINVAL;
584 }
585
586 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
587 return 0;
588 }
589
590 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
591 {
592 u32 status, count = 100;
593
594 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
595 while (count) {
596 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
597 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
598 break;
599 /*
600 * entering config mode can take as long as the rendering
601 * of a full frame, hence the long sleep here
602 */
603 usleep_range(1000, 10000);
604 count--;
605 }
606 WARN(count == 0, "timeout while entering config mode");
607 }
608
609 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
610 {
611 u32 status, count = 100;
612
613 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
614 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
615 while (count) {
616 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
617 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
618 break;
619 usleep_range(100, 1000);
620 count--;
621 }
622 WARN(count == 0, "timeout while leaving config mode");
623 }
624
625 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
626 {
627 u32 status;
628
629 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
630 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
631 return true;
632
633 return false;
634 }
635
636 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
637 {
638 if (value)
639 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
640 else
641 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
642 }
643
644 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
645 {
646 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
647
648 malidp_hw_write(hwdev, hwdev->output_color_depth,
649 hwdev->hw->map.out_depth_base);
650 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
651 /*
652 * Mali-DP550 and Mali-DP650 encode the background color like this:
653 * - red @ MALIDP550_DE_BGND_COLOR[23:16]
654 * - green @ MALIDP550_DE_BGND_COLOR[15:8]
655 * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
656 *
657 * We need to truncate the least significant 4 bits from the default
658 * MALIDP_BGND_COLOR_x values
659 */
660 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
661 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
662 ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
663 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
664
665 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
666 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
667 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
668
669 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
670 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
671 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
672
673 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
674 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
675 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
676 val |= MALIDP550_HSYNCPOL;
677 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
678 val |= MALIDP550_VSYNCPOL;
679 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
680
681 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
682 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
683
684 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
685 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
686 else
687 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
688 }
689
690 static int malidpx50_get_bytes_per_column(u32 fmt)
691 {
692 u32 bytes_per_column;
693
694 switch (fmt) {
695 /* 8 lines at 4 bytes per pixel */
696 case DRM_FORMAT_ARGB2101010:
697 case DRM_FORMAT_ABGR2101010:
698 case DRM_FORMAT_RGBA1010102:
699 case DRM_FORMAT_BGRA1010102:
700 case DRM_FORMAT_ARGB8888:
701 case DRM_FORMAT_ABGR8888:
702 case DRM_FORMAT_RGBA8888:
703 case DRM_FORMAT_BGRA8888:
704 case DRM_FORMAT_XRGB8888:
705 case DRM_FORMAT_XBGR8888:
706 case DRM_FORMAT_RGBX8888:
707 case DRM_FORMAT_BGRX8888:
708 case DRM_FORMAT_RGB888:
709 case DRM_FORMAT_BGR888:
710 /* 16 lines at 2 bytes per pixel */
711 case DRM_FORMAT_RGBA5551:
712 case DRM_FORMAT_ABGR1555:
713 case DRM_FORMAT_RGB565:
714 case DRM_FORMAT_BGR565:
715 case DRM_FORMAT_UYVY:
716 case DRM_FORMAT_YUYV:
717 case DRM_FORMAT_X0L0:
718 bytes_per_column = 32;
719 break;
720 /* 16 lines at 1.5 bytes per pixel */
721 case DRM_FORMAT_NV12:
722 case DRM_FORMAT_YUV420:
723 /* 8 lines at 3 bytes per pixel */
724 case DRM_FORMAT_VUY888:
725 /* 16 lines at 12 bits per pixel */
726 case DRM_FORMAT_YUV420_8BIT:
727 /* 8 lines at 3 bytes per pixel */
728 case DRM_FORMAT_P010:
729 bytes_per_column = 24;
730 break;
731 /* 8 lines at 30 bits per pixel */
732 case DRM_FORMAT_VUY101010:
733 /* 16 lines at 15 bits per pixel */
734 case DRM_FORMAT_YUV420_10BIT:
735 bytes_per_column = 30;
736 break;
737 default:
738 return -EINVAL;
739 }
740
741 return bytes_per_column;
742 }
743
744 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
745 u16 h, u32 fmt, bool has_modifier)
746 {
747 int bytes_per_column = 0;
748
749 switch (fmt) {
750 /* 8 lines at 15 bits per pixel */
751 case DRM_FORMAT_YUV420_10BIT:
752 bytes_per_column = 15;
753 break;
754 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
755 case DRM_FORMAT_X0L2:
756 if (has_modifier)
757 bytes_per_column = 8;
758 else
759 return -EINVAL;
760 break;
761 default:
762 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
763 }
764
765 if (bytes_per_column == -EINVAL)
766 return bytes_per_column;
767
768 return w * bytes_per_column;
769 }
770
771 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
772 u16 h, u32 fmt, bool has_modifier)
773 {
774 int bytes_per_column = 0;
775
776 switch (fmt) {
777 /* 16 lines at 2 bytes per pixel */
778 case DRM_FORMAT_X0L2:
779 bytes_per_column = 32;
780 break;
781 default:
782 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
783 }
784
785 if (bytes_per_column == -EINVAL)
786 return bytes_per_column;
787
788 return w * bytes_per_column;
789 }
790
791 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
792 struct malidp_se_config *se_config,
793 struct malidp_se_config *old_config)
794 {
795 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
796 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
797 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
798 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
799
800 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
801 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
802 return 0;
803 }
804
805 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
806 struct malidp_se_config *se_config,
807 struct videomode *vm)
808 {
809 unsigned long mclk;
810 unsigned long pxlclk = vm->pixelclock;
811 unsigned long htotal = vm->hactive + vm->hfront_porch +
812 vm->hback_porch + vm->hsync_len;
813 unsigned long numerator = 1, denominator = 1;
814 long ret;
815
816 if (se_config->scale_enable) {
817 numerator = max(se_config->input_w, se_config->output_w) *
818 se_config->input_h;
819 numerator += se_config->output_w *
820 (se_config->output_h -
821 min(se_config->input_h, se_config->output_h));
822 denominator = (htotal - 2) * se_config->output_h;
823 }
824
825 /* mclk can't be slower than pxlclk. */
826 if (numerator < denominator)
827 numerator = denominator = 1;
828 mclk = (pxlclk * numerator) / denominator;
829 ret = clk_get_rate(hwdev->mclk);
830 if (ret < mclk) {
831 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
832 mclk / 1000);
833 return -EINVAL;
834 }
835 return ret;
836 }
837
838 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
839 dma_addr_t *addrs, s32 *pitches,
840 int num_planes, u16 w, u16 h, u32 fmt_id,
841 const s16 *rgb2yuv_coeffs)
842 {
843 u32 base = MALIDP550_SE_MEMWRITE_BASE;
844 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
845
846 /* enable the scaling engine block */
847 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
848
849 hwdev->mw_state = MW_ONESHOT;
850
851 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
852 switch (num_planes) {
853 case 2:
854 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
855 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
856 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
857 /* fall through */
858 case 1:
859 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
860 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
861 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
862 break;
863 default:
864 WARN(1, "Invalid number of planes");
865 }
866
867 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
868 MALIDP550_SE_MEMWRITE_OUT_SIZE);
869 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
870 MALIDP550_SE_CONTROL);
871
872 if (rgb2yuv_coeffs) {
873 int i;
874
875 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
876 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
877 MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
878 }
879 }
880
881 return 0;
882 }
883
884 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
885 {
886 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
887
888 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
889 MALIDP550_SE_CONTROL);
890 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
891 }
892
893 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
894 {
895 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
896 u8 ln_size = (conf >> 4) & 0x3, rsize;
897
898 hwdev->min_line_size = 4;
899
900 switch (ln_size) {
901 case 0:
902 case 2:
903 /* reserved values */
904 hwdev->max_line_size = 0;
905 return -EINVAL;
906 case 1:
907 hwdev->max_line_size = SZ_4K;
908 /* two banks of 128KB for rotation memory */
909 rsize = 128;
910 break;
911 case 3:
912 hwdev->max_line_size = 2560;
913 /* two banks of 80KB for rotation memory */
914 rsize = 80;
915 }
916
917 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
918 return 0;
919 }
920
921 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
922 [MALIDP_500] = {
923 .map = {
924 .coeffs_base = MALIDP500_COEFFS_BASE,
925 .se_base = MALIDP500_SE_BASE,
926 .dc_base = MALIDP500_DC_BASE,
927 .out_depth_base = MALIDP500_OUTPUT_DEPTH,
928 .features = 0, /* no CLEARIRQ register */
929 .n_layers = ARRAY_SIZE(malidp500_layers),
930 .layers = malidp500_layers,
931 .de_irq_map = {
932 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
933 MALIDP500_DE_IRQ_AXI_ERR |
934 MALIDP500_DE_IRQ_VSYNC |
935 MALIDP500_DE_IRQ_GLOBAL,
936 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
937 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
938 MALIDP500_DE_IRQ_AXI_ERR |
939 MALIDP500_DE_IRQ_SATURATION,
940 },
941 .se_irq_map = {
942 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
943 MALIDP500_SE_IRQ_CONF_VALID |
944 MALIDP500_SE_IRQ_GLOBAL,
945 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
946 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
947 MALIDP500_SE_IRQ_AXI_ERROR |
948 MALIDP500_SE_IRQ_OVERRUN,
949 },
950 .dc_irq_map = {
951 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
952 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
953 },
954 .pixel_formats = malidp500_de_formats,
955 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
956 .bus_align_bytes = 8,
957 },
958 .query_hw = malidp500_query_hw,
959 .enter_config_mode = malidp500_enter_config_mode,
960 .leave_config_mode = malidp500_leave_config_mode,
961 .in_config_mode = malidp500_in_config_mode,
962 .set_config_valid = malidp500_set_config_valid,
963 .modeset = malidp500_modeset,
964 .rotmem_required = malidp500_rotmem_required,
965 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
966 .se_calc_mclk = malidp500_se_calc_mclk,
967 .enable_memwrite = malidp500_enable_memwrite,
968 .disable_memwrite = malidp500_disable_memwrite,
969 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
970 },
971 [MALIDP_550] = {
972 .map = {
973 .coeffs_base = MALIDP550_COEFFS_BASE,
974 .se_base = MALIDP550_SE_BASE,
975 .dc_base = MALIDP550_DC_BASE,
976 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
977 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
978 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
979 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
980 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
981 .n_layers = ARRAY_SIZE(malidp550_layers),
982 .layers = malidp550_layers,
983 .de_irq_map = {
984 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
985 MALIDP550_DE_IRQ_VSYNC,
986 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
987 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
988 MALIDP550_DE_IRQ_SATURATION |
989 MALIDP550_DE_IRQ_AXI_ERR,
990 },
991 .se_irq_map = {
992 .irq_mask = MALIDP550_SE_IRQ_EOW,
993 .vsync_irq = MALIDP550_SE_IRQ_EOW,
994 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
995 MALIDP550_SE_IRQ_OVR |
996 MALIDP550_SE_IRQ_IBSY,
997 },
998 .dc_irq_map = {
999 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1000 MALIDP550_DC_IRQ_SE,
1001 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1002 },
1003 .pixel_formats = malidp550_de_formats,
1004 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1005 .bus_align_bytes = 8,
1006 },
1007 .query_hw = malidp550_query_hw,
1008 .enter_config_mode = malidp550_enter_config_mode,
1009 .leave_config_mode = malidp550_leave_config_mode,
1010 .in_config_mode = malidp550_in_config_mode,
1011 .set_config_valid = malidp550_set_config_valid,
1012 .modeset = malidp550_modeset,
1013 .rotmem_required = malidp550_rotmem_required,
1014 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1015 .se_calc_mclk = malidp550_se_calc_mclk,
1016 .enable_memwrite = malidp550_enable_memwrite,
1017 .disable_memwrite = malidp550_disable_memwrite,
1018 .features = 0,
1019 },
1020 [MALIDP_650] = {
1021 .map = {
1022 .coeffs_base = MALIDP550_COEFFS_BASE,
1023 .se_base = MALIDP550_SE_BASE,
1024 .dc_base = MALIDP550_DC_BASE,
1025 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
1026 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
1027 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
1028 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
1029 .n_layers = ARRAY_SIZE(malidp650_layers),
1030 .layers = malidp650_layers,
1031 .de_irq_map = {
1032 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1033 MALIDP650_DE_IRQ_DRIFT |
1034 MALIDP550_DE_IRQ_VSYNC,
1035 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1036 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1037 MALIDP650_DE_IRQ_DRIFT |
1038 MALIDP550_DE_IRQ_SATURATION |
1039 MALIDP550_DE_IRQ_AXI_ERR |
1040 MALIDP650_DE_IRQ_ACEV1 |
1041 MALIDP650_DE_IRQ_ACEV2 |
1042 MALIDP650_DE_IRQ_ACEG |
1043 MALIDP650_DE_IRQ_AXIEP,
1044 },
1045 .se_irq_map = {
1046 .irq_mask = MALIDP550_SE_IRQ_EOW,
1047 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1048 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1049 MALIDP550_SE_IRQ_OVR |
1050 MALIDP550_SE_IRQ_IBSY,
1051 },
1052 .dc_irq_map = {
1053 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1054 MALIDP550_DC_IRQ_SE,
1055 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1056 },
1057 .pixel_formats = malidp650_de_formats,
1058 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1059 .bus_align_bytes = 16,
1060 },
1061 .query_hw = malidp650_query_hw,
1062 .enter_config_mode = malidp550_enter_config_mode,
1063 .leave_config_mode = malidp550_leave_config_mode,
1064 .in_config_mode = malidp550_in_config_mode,
1065 .set_config_valid = malidp550_set_config_valid,
1066 .modeset = malidp550_modeset,
1067 .rotmem_required = malidp650_rotmem_required,
1068 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1069 .se_calc_mclk = malidp550_se_calc_mclk,
1070 .enable_memwrite = malidp550_enable_memwrite,
1071 .disable_memwrite = malidp550_disable_memwrite,
1072 .features = 0,
1073 },
1074 };
1075
1076 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
1077 u8 layer_id, u32 format, bool has_modifier)
1078 {
1079 unsigned int i;
1080
1081 for (i = 0; i < map->n_pixel_formats; i++) {
1082 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
1083 (map->pixel_formats[i].format == format)) {
1084 /*
1085 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1086 * is supported by a different h/w format id than
1087 * DRM_FORMAT_YUYV (only).
1088 */
1089 if (format == DRM_FORMAT_YUYV &&
1090 (has_modifier) &&
1091 (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
1092 return AFBC_YUV_422_FORMAT_ID;
1093 else
1094 return map->pixel_formats[i].id;
1095 }
1096 }
1097
1098 return MALIDP_INVALID_FORMAT_ID;
1099 }
1100
1101 bool malidp_hw_format_is_linear_only(u32 format)
1102 {
1103 switch (format) {
1104 case DRM_FORMAT_ARGB2101010:
1105 case DRM_FORMAT_RGBA1010102:
1106 case DRM_FORMAT_BGRA1010102:
1107 case DRM_FORMAT_ARGB8888:
1108 case DRM_FORMAT_RGBA8888:
1109 case DRM_FORMAT_BGRA8888:
1110 case DRM_FORMAT_XBGR8888:
1111 case DRM_FORMAT_XRGB8888:
1112 case DRM_FORMAT_RGBX8888:
1113 case DRM_FORMAT_BGRX8888:
1114 case DRM_FORMAT_RGB888:
1115 case DRM_FORMAT_RGB565:
1116 case DRM_FORMAT_ARGB1555:
1117 case DRM_FORMAT_RGBA5551:
1118 case DRM_FORMAT_BGRA5551:
1119 case DRM_FORMAT_UYVY:
1120 case DRM_FORMAT_XYUV8888:
1121 case DRM_FORMAT_XVYU2101010:
1122 case DRM_FORMAT_X0L2:
1123 case DRM_FORMAT_X0L0:
1124 return true;
1125 default:
1126 return false;
1127 }
1128 }
1129
1130 bool malidp_hw_format_is_afbc_only(u32 format)
1131 {
1132 switch (format) {
1133 case DRM_FORMAT_VUY888:
1134 case DRM_FORMAT_VUY101010:
1135 case DRM_FORMAT_YUV420_8BIT:
1136 case DRM_FORMAT_YUV420_10BIT:
1137 return true;
1138 default:
1139 return false;
1140 }
1141 }
1142
1143 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1144 {
1145 u32 base = malidp_get_block_base(hwdev, block);
1146
1147 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1148 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1149 else
1150 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1151 }
1152
1153 static irqreturn_t malidp_de_irq(int irq, void *arg)
1154 {
1155 struct drm_device *drm = arg;
1156 struct malidp_drm *malidp = drm->dev_private;
1157 struct malidp_hw_device *hwdev;
1158 struct malidp_hw *hw;
1159 const struct malidp_irq_map *de;
1160 u32 status, mask, dc_status;
1161 irqreturn_t ret = IRQ_NONE;
1162
1163 hwdev = malidp->dev;
1164 hw = hwdev->hw;
1165 de = &hw->map.de_irq_map;
1166
1167 /*
1168 * if we are suspended it is likely that we were invoked because
1169 * we share an interrupt line with some other driver, don't try
1170 * to read the hardware registers
1171 */
1172 if (hwdev->pm_suspended)
1173 return IRQ_NONE;
1174
1175 /* first handle the config valid IRQ */
1176 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1177 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1178 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1179 /* do we have a page flip event? */
1180 if (malidp->event != NULL) {
1181 spin_lock(&drm->event_lock);
1182 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1183 malidp->event = NULL;
1184 spin_unlock(&drm->event_lock);
1185 }
1186 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1187 ret = IRQ_WAKE_THREAD;
1188 }
1189
1190 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1191 if (!(status & de->irq_mask))
1192 return ret;
1193
1194 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1195 /* keep the status of the enabled interrupts, plus the error bits */
1196 status &= (mask | de->err_mask);
1197 if ((status & de->vsync_irq) && malidp->crtc.enabled)
1198 drm_crtc_handle_vblank(&malidp->crtc);
1199
1200 #ifdef CONFIG_DEBUG_FS
1201 if (status & de->err_mask) {
1202 malidp_error(malidp, &malidp->de_errors, status,
1203 drm_crtc_vblank_count(&malidp->crtc));
1204 }
1205 #endif
1206 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1207
1208 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1209 }
1210
1211 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1212 {
1213 struct drm_device *drm = arg;
1214 struct malidp_drm *malidp = drm->dev_private;
1215
1216 wake_up(&malidp->wq);
1217
1218 return IRQ_HANDLED;
1219 }
1220
1221 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1222 {
1223 /* ensure interrupts are disabled */
1224 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1225 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1226 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1227 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1228
1229 /* first enable the DC block IRQs */
1230 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1231 hwdev->hw->map.dc_irq_map.irq_mask);
1232
1233 /* now enable the DE block IRQs */
1234 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1235 hwdev->hw->map.de_irq_map.irq_mask);
1236 }
1237
1238 int malidp_de_irq_init(struct drm_device *drm, int irq)
1239 {
1240 struct malidp_drm *malidp = drm->dev_private;
1241 struct malidp_hw_device *hwdev = malidp->dev;
1242 int ret;
1243
1244 /* ensure interrupts are disabled */
1245 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1246 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1247 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1248 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1249
1250 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1251 malidp_de_irq_thread_handler,
1252 IRQF_SHARED, "malidp-de", drm);
1253 if (ret < 0) {
1254 DRM_ERROR("failed to install DE IRQ handler\n");
1255 return ret;
1256 }
1257
1258 malidp_de_irq_hw_init(hwdev);
1259
1260 return 0;
1261 }
1262
1263 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1264 {
1265 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1266 hwdev->hw->map.de_irq_map.irq_mask);
1267 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1268 hwdev->hw->map.dc_irq_map.irq_mask);
1269 }
1270
1271 static irqreturn_t malidp_se_irq(int irq, void *arg)
1272 {
1273 struct drm_device *drm = arg;
1274 struct malidp_drm *malidp = drm->dev_private;
1275 struct malidp_hw_device *hwdev = malidp->dev;
1276 struct malidp_hw *hw = hwdev->hw;
1277 const struct malidp_irq_map *se = &hw->map.se_irq_map;
1278 u32 status, mask;
1279
1280 /*
1281 * if we are suspended it is likely that we were invoked because
1282 * we share an interrupt line with some other driver, don't try
1283 * to read the hardware registers
1284 */
1285 if (hwdev->pm_suspended)
1286 return IRQ_NONE;
1287
1288 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1289 if (!(status & (se->irq_mask | se->err_mask)))
1290 return IRQ_NONE;
1291
1292 #ifdef CONFIG_DEBUG_FS
1293 if (status & se->err_mask)
1294 malidp_error(malidp, &malidp->se_errors, status,
1295 drm_crtc_vblank_count(&malidp->crtc));
1296 #endif
1297 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1298 status &= mask;
1299
1300 if (status & se->vsync_irq) {
1301 switch (hwdev->mw_state) {
1302 case MW_ONESHOT:
1303 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1304 break;
1305 case MW_STOP:
1306 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1307 /* disable writeback after stop */
1308 hwdev->mw_state = MW_NOT_ENABLED;
1309 break;
1310 case MW_RESTART:
1311 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1312 /* fall through to a new start */
1313 case MW_START:
1314 /* writeback started, need to emulate one-shot mode */
1315 hw->disable_memwrite(hwdev);
1316 /*
1317 * only set config_valid HW bit if there is no other update
1318 * in progress or if we raced ahead of the DE IRQ handler
1319 * and config_valid flag will not be update until later
1320 */
1321 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1322 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1323 (status & hw->map.dc_irq_map.vsync_irq))
1324 hw->set_config_valid(hwdev, 1);
1325 break;
1326 }
1327 }
1328
1329 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1330
1331 return IRQ_HANDLED;
1332 }
1333
1334 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1335 {
1336 /* ensure interrupts are disabled */
1337 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1338 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1339
1340 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1341 hwdev->hw->map.se_irq_map.irq_mask);
1342 }
1343
1344 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1345 {
1346 return IRQ_HANDLED;
1347 }
1348
1349 int malidp_se_irq_init(struct drm_device *drm, int irq)
1350 {
1351 struct malidp_drm *malidp = drm->dev_private;
1352 struct malidp_hw_device *hwdev = malidp->dev;
1353 int ret;
1354
1355 /* ensure interrupts are disabled */
1356 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1357 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1358
1359 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1360 malidp_se_irq_thread_handler,
1361 IRQF_SHARED, "malidp-se", drm);
1362 if (ret < 0) {
1363 DRM_ERROR("failed to install SE IRQ handler\n");
1364 return ret;
1365 }
1366
1367 hwdev->mw_state = MW_NOT_ENABLED;
1368 malidp_se_irq_hw_init(hwdev);
1369
1370 return 0;
1371 }
1372
1373 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1374 {
1375 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1376 hwdev->hw->map.se_irq_map.irq_mask);
1377 }