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