1 // SPDX-License-Identifier: GPL-2.0-only
3 * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
4 * Author: Liviu Dudau <Liviu.Dudau@arm.com>
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
11 #include <linux/clk.h>
12 #include <linux/types.h>
15 #include <video/videomode.h>
16 #include <video/display_timing.h>
18 #include "malidp_drv.h"
19 #include "malidp_hw.h"
20 #include "malidp_mw.h"
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 */
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 }
56 #define MALIDP_ID(__group, __format) \
57 ((((__group) & 0x7) << 3) | ((__format) & 0x7))
59 #define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
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)}
101 static const struct malidp_format_id malidp550_de_formats
[] = {
102 MALIDP_COMMON_FORMATS
,
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)},
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
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
},
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
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 },
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,
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
,
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
),
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
),
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
),
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
),
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
),
184 DRM_FORMAT_MOD_LINEAR
,
186 DRM_FORMAT_MOD_INVALID
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
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
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
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
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
263 #define MALIDP_DE_DEFAULT_PREFETCH_START 5
265 static int malidp500_query_hw(struct malidp_hw_device
*hwdev
)
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;
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 */
279 static void malidp500_enter_config_mode(struct malidp_hw_device
*hwdev
)
281 u32 status
, count
= 100;
283 malidp_hw_setbits(hwdev
, MALIDP500_DC_CONFIG_REQ
, MALIDP500_DC_CONTROL
);
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
)
289 * entering config mode can take as long as the rendering
290 * of a full frame, hence the long sleep here
292 usleep_range(1000, 10000);
295 WARN(count
== 0, "timeout while entering config mode");
298 static void malidp500_leave_config_mode(struct malidp_hw_device
*hwdev
)
300 u32 status
, count
= 100;
302 malidp_hw_clearbits(hwdev
, MALIDP_CFG_VALID
, MALIDP500_CONFIG_VALID
);
303 malidp_hw_clearbits(hwdev
, MALIDP500_DC_CONFIG_REQ
, MALIDP500_DC_CONTROL
);
305 status
= malidp_hw_read(hwdev
, hwdev
->hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
306 if ((status
& MALIDP500_DC_CONFIG_REQ
) == 0)
308 usleep_range(100, 1000);
311 WARN(count
== 0, "timeout while leaving config mode");
314 static bool malidp500_in_config_mode(struct malidp_hw_device
*hwdev
)
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
)
325 static void malidp500_set_config_valid(struct malidp_hw_device
*hwdev
, u8 value
)
328 malidp_hw_setbits(hwdev
, MALIDP_CFG_VALID
, MALIDP500_CONFIG_VALID
);
330 malidp_hw_clearbits(hwdev
, MALIDP_CFG_VALID
, MALIDP500_CONFIG_VALID
);
333 static void malidp500_modeset(struct malidp_hw_device
*hwdev
, struct videomode
*mode
)
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
);
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]
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);
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
);
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
);
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
);
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
);
373 if (mode
->flags
& DISPLAY_FLAGS_INTERLACED
)
374 malidp_hw_setbits(hwdev
, MALIDP_DISP_FUNC_ILACED
, MALIDP_DE_DISPLAY_FUNC
);
376 malidp_hw_clearbits(hwdev
, MALIDP_DISP_FUNC_ILACED
, MALIDP_DE_DISPLAY_FUNC
);
379 int malidp_format_get_bpp(u32 fmt
)
381 int bpp
= drm_format_plane_cpp(fmt
, 0) * 8;
385 case DRM_FORMAT_VUY101010
:
387 case DRM_FORMAT_YUV420_10BIT
:
390 case DRM_FORMAT_YUV420_8BIT
:
401 static int malidp500_rotmem_required(struct malidp_hw_device
*hwdev
, u16 w
,
402 u16 h
, u32 fmt
, bool has_modifier
)
405 * Each layer needs enough rotation memory to fit 8 lines
406 * worth of pixel data. Required size is then:
407 * size = rotated_width * (bpp / 8) * 8;
409 int bpp
= malidp_format_get_bpp(fmt
);
414 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device
*hwdev
,
420 u16 scaling_control
= MALIDP500_SE_CONTROL
+ MALIDP_SE_SCALING_CONTROL
;
422 malidp_hw_write(hwdev
,
423 direction
| (addr
& MALIDP_SE_COEFFTAB_ADDR_MASK
),
424 scaling_control
+ MALIDP_SE_COEFFTAB_ADDR
);
425 for (i
= 0; i
< ARRAY_SIZE(dp500_se_scaling_coeffs
); ++i
)
426 malidp_hw_write(hwdev
, MALIDP_SE_SET_COEFFTAB_DATA(
427 dp500_se_scaling_coeffs
[coeffs_id
][i
]),
428 scaling_control
+ MALIDP_SE_COEFFTAB_DATA
);
431 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device
*hwdev
,
432 struct malidp_se_config
*se_config
,
433 struct malidp_se_config
*old_config
)
435 /* Get array indices into dp500_se_scaling_coeffs. */
436 u8 h
= (u8
)se_config
->hcoeff
- 1;
437 u8 v
= (u8
)se_config
->vcoeff
- 1;
439 if (WARN_ON(h
>= ARRAY_SIZE(dp500_se_scaling_coeffs
) ||
440 v
>= ARRAY_SIZE(dp500_se_scaling_coeffs
)))
443 if ((h
== v
) && (se_config
->hcoeff
!= old_config
->hcoeff
||
444 se_config
->vcoeff
!= old_config
->vcoeff
)) {
445 malidp500_se_write_pp_coefftab(hwdev
,
446 (MALIDP_SE_V_COEFFTAB
|
447 MALIDP_SE_H_COEFFTAB
),
450 if (se_config
->vcoeff
!= old_config
->vcoeff
)
451 malidp500_se_write_pp_coefftab(hwdev
,
452 MALIDP_SE_V_COEFFTAB
,
454 if (se_config
->hcoeff
!= old_config
->hcoeff
)
455 malidp500_se_write_pp_coefftab(hwdev
,
456 MALIDP_SE_H_COEFFTAB
,
463 static long malidp500_se_calc_mclk(struct malidp_hw_device
*hwdev
,
464 struct malidp_se_config
*se_config
,
465 struct videomode
*vm
)
468 unsigned long pxlclk
= vm
->pixelclock
; /* Hz */
469 unsigned long htotal
= vm
->hactive
+ vm
->hfront_porch
+
470 vm
->hback_porch
+ vm
->hsync_len
;
471 unsigned long input_size
= se_config
->input_w
* se_config
->input_h
;
472 unsigned long a
= 10;
476 * mclk = max(a, 1.5) * pxlclk
478 * To avoid float calculaiton, using 15 instead of 1.5 and div by
481 if (se_config
->scale_enable
) {
482 a
= 15 * input_size
/ (htotal
* se_config
->output_h
);
486 mclk
= a
* pxlclk
/ 10;
487 ret
= clk_get_rate(hwdev
->mclk
);
489 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
496 static int malidp500_enable_memwrite(struct malidp_hw_device
*hwdev
,
497 dma_addr_t
*addrs
, s32
*pitches
,
498 int num_planes
, u16 w
, u16 h
, u32 fmt_id
,
499 const s16
*rgb2yuv_coeffs
)
501 u32 base
= MALIDP500_SE_MEMWRITE_BASE
;
502 u32 de_base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
504 /* enable the scaling engine block */
505 malidp_hw_setbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, de_base
+ MALIDP_DE_DISPLAY_FUNC
);
507 /* restart the writeback if already enabled */
508 if (hwdev
->mw_state
!= MW_NOT_ENABLED
)
509 hwdev
->mw_state
= MW_RESTART
;
511 hwdev
->mw_state
= MW_START
;
513 malidp_hw_write(hwdev
, fmt_id
, base
+ MALIDP_MW_FORMAT
);
514 switch (num_planes
) {
516 malidp_hw_write(hwdev
, lower_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_LOW
);
517 malidp_hw_write(hwdev
, upper_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_HIGH
);
518 malidp_hw_write(hwdev
, pitches
[1], base
+ MALIDP_MW_P2_STRIDE
);
521 malidp_hw_write(hwdev
, lower_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_LOW
);
522 malidp_hw_write(hwdev
, upper_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_HIGH
);
523 malidp_hw_write(hwdev
, pitches
[0], base
+ MALIDP_MW_P1_STRIDE
);
526 WARN(1, "Invalid number of planes");
529 malidp_hw_write(hwdev
, MALIDP_DE_H_ACTIVE(w
) | MALIDP_DE_V_ACTIVE(h
),
530 MALIDP500_SE_MEMWRITE_OUT_SIZE
);
532 if (rgb2yuv_coeffs
) {
535 for (i
= 0; i
< MALIDP_COLORADJ_NUM_COEFFS
; i
++) {
536 malidp_hw_write(hwdev
, rgb2yuv_coeffs
[i
],
537 MALIDP500_SE_RGB_YUV_COEFFS
+ i
* 4);
541 malidp_hw_setbits(hwdev
, MALIDP_SE_MEMWRITE_EN
, MALIDP500_SE_CONTROL
);
546 static void malidp500_disable_memwrite(struct malidp_hw_device
*hwdev
)
548 u32 base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
550 if (hwdev
->mw_state
== MW_START
|| hwdev
->mw_state
== MW_RESTART
)
551 hwdev
->mw_state
= MW_STOP
;
552 malidp_hw_clearbits(hwdev
, MALIDP_SE_MEMWRITE_EN
, MALIDP500_SE_CONTROL
);
553 malidp_hw_clearbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, base
+ MALIDP_DE_DISPLAY_FUNC
);
556 static int malidp550_query_hw(struct malidp_hw_device
*hwdev
)
558 u32 conf
= malidp_hw_read(hwdev
, MALIDP550_CONFIG_ID
);
559 u8 ln_size
= (conf
>> 4) & 0x3, rsize
;
561 hwdev
->min_line_size
= 2;
565 hwdev
->max_line_size
= SZ_2K
;
566 /* two banks of 64KB for rotation memory */
570 hwdev
->max_line_size
= SZ_4K
;
571 /* two banks of 128KB for rotation memory */
575 hwdev
->max_line_size
= 1280;
576 /* two banks of 40KB for rotation memory */
581 hwdev
->max_line_size
= 0;
585 hwdev
->rotation_memory
[0] = hwdev
->rotation_memory
[1] = rsize
* SZ_1K
;
589 static void malidp550_enter_config_mode(struct malidp_hw_device
*hwdev
)
591 u32 status
, count
= 100;
593 malidp_hw_setbits(hwdev
, MALIDP550_DC_CONFIG_REQ
, MALIDP550_DC_CONTROL
);
595 status
= malidp_hw_read(hwdev
, hwdev
->hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
596 if ((status
& MALIDP550_DC_CONFIG_REQ
) == MALIDP550_DC_CONFIG_REQ
)
599 * entering config mode can take as long as the rendering
600 * of a full frame, hence the long sleep here
602 usleep_range(1000, 10000);
605 WARN(count
== 0, "timeout while entering config mode");
608 static void malidp550_leave_config_mode(struct malidp_hw_device
*hwdev
)
610 u32 status
, count
= 100;
612 malidp_hw_clearbits(hwdev
, MALIDP_CFG_VALID
, MALIDP550_CONFIG_VALID
);
613 malidp_hw_clearbits(hwdev
, MALIDP550_DC_CONFIG_REQ
, MALIDP550_DC_CONTROL
);
615 status
= malidp_hw_read(hwdev
, hwdev
->hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
616 if ((status
& MALIDP550_DC_CONFIG_REQ
) == 0)
618 usleep_range(100, 1000);
621 WARN(count
== 0, "timeout while leaving config mode");
624 static bool malidp550_in_config_mode(struct malidp_hw_device
*hwdev
)
628 status
= malidp_hw_read(hwdev
, hwdev
->hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
629 if ((status
& MALIDP550_DC_CONFIG_REQ
) == MALIDP550_DC_CONFIG_REQ
)
635 static void malidp550_set_config_valid(struct malidp_hw_device
*hwdev
, u8 value
)
638 malidp_hw_setbits(hwdev
, MALIDP_CFG_VALID
, MALIDP550_CONFIG_VALID
);
640 malidp_hw_clearbits(hwdev
, MALIDP_CFG_VALID
, MALIDP550_CONFIG_VALID
);
643 static void malidp550_modeset(struct malidp_hw_device
*hwdev
, struct videomode
*mode
)
645 u32 val
= MALIDP_DE_DEFAULT_PREFETCH_START
;
647 malidp_hw_write(hwdev
, hwdev
->output_color_depth
,
648 hwdev
->hw
->map
.out_depth_base
);
649 malidp_hw_write(hwdev
, val
, MALIDP550_DE_CONTROL
);
651 * Mali-DP550 and Mali-DP650 encode the background color like this:
652 * - red @ MALIDP550_DE_BGND_COLOR[23:16]
653 * - green @ MALIDP550_DE_BGND_COLOR[15:8]
654 * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
656 * We need to truncate the least significant 4 bits from the default
657 * MALIDP_BGND_COLOR_x values
659 val
= (((MALIDP_BGND_COLOR_R
>> 4) & 0xff) << 16) |
660 (((MALIDP_BGND_COLOR_G
>> 4) & 0xff) << 8) |
661 ((MALIDP_BGND_COLOR_B
>> 4) & 0xff);
662 malidp_hw_write(hwdev
, val
, MALIDP550_DE_BGND_COLOR
);
664 val
= MALIDP_DE_H_FRONTPORCH(mode
->hfront_porch
) |
665 MALIDP_DE_H_BACKPORCH(mode
->hback_porch
);
666 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_H_TIMINGS
);
668 val
= MALIDP550_DE_V_FRONTPORCH(mode
->vfront_porch
) |
669 MALIDP_DE_V_BACKPORCH(mode
->vback_porch
);
670 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_V_TIMINGS
);
672 val
= MALIDP_DE_H_SYNCWIDTH(mode
->hsync_len
) |
673 MALIDP_DE_V_SYNCWIDTH(mode
->vsync_len
);
674 if (mode
->flags
& DISPLAY_FLAGS_HSYNC_HIGH
)
675 val
|= MALIDP550_HSYNCPOL
;
676 if (mode
->flags
& DISPLAY_FLAGS_VSYNC_HIGH
)
677 val
|= MALIDP550_VSYNCPOL
;
678 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_SYNC_WIDTH
);
680 val
= MALIDP_DE_H_ACTIVE(mode
->hactive
) | MALIDP_DE_V_ACTIVE(mode
->vactive
);
681 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_HV_ACTIVE
);
683 if (mode
->flags
& DISPLAY_FLAGS_INTERLACED
)
684 malidp_hw_setbits(hwdev
, MALIDP_DISP_FUNC_ILACED
, MALIDP_DE_DISPLAY_FUNC
);
686 malidp_hw_clearbits(hwdev
, MALIDP_DISP_FUNC_ILACED
, MALIDP_DE_DISPLAY_FUNC
);
689 static int malidpx50_get_bytes_per_column(u32 fmt
)
691 u32 bytes_per_column
;
694 /* 8 lines at 4 bytes per pixel */
695 case DRM_FORMAT_ARGB2101010
:
696 case DRM_FORMAT_ABGR2101010
:
697 case DRM_FORMAT_RGBA1010102
:
698 case DRM_FORMAT_BGRA1010102
:
699 case DRM_FORMAT_ARGB8888
:
700 case DRM_FORMAT_ABGR8888
:
701 case DRM_FORMAT_RGBA8888
:
702 case DRM_FORMAT_BGRA8888
:
703 case DRM_FORMAT_XRGB8888
:
704 case DRM_FORMAT_XBGR8888
:
705 case DRM_FORMAT_RGBX8888
:
706 case DRM_FORMAT_BGRX8888
:
707 case DRM_FORMAT_RGB888
:
708 case DRM_FORMAT_BGR888
:
709 /* 16 lines at 2 bytes per pixel */
710 case DRM_FORMAT_RGBA5551
:
711 case DRM_FORMAT_ABGR1555
:
712 case DRM_FORMAT_RGB565
:
713 case DRM_FORMAT_BGR565
:
714 case DRM_FORMAT_UYVY
:
715 case DRM_FORMAT_YUYV
:
716 case DRM_FORMAT_X0L0
:
717 bytes_per_column
= 32;
719 /* 16 lines at 1.5 bytes per pixel */
720 case DRM_FORMAT_NV12
:
721 case DRM_FORMAT_YUV420
:
722 /* 8 lines at 3 bytes per pixel */
723 case DRM_FORMAT_VUY888
:
724 /* 16 lines at 12 bits per pixel */
725 case DRM_FORMAT_YUV420_8BIT
:
726 /* 8 lines at 3 bytes per pixel */
727 case DRM_FORMAT_P010
:
728 bytes_per_column
= 24;
730 /* 8 lines at 30 bits per pixel */
731 case DRM_FORMAT_VUY101010
:
732 /* 16 lines at 15 bits per pixel */
733 case DRM_FORMAT_YUV420_10BIT
:
734 bytes_per_column
= 30;
740 return bytes_per_column
;
743 static int malidp550_rotmem_required(struct malidp_hw_device
*hwdev
, u16 w
,
744 u16 h
, u32 fmt
, bool has_modifier
)
746 int bytes_per_column
= 0;
749 /* 8 lines at 15 bits per pixel */
750 case DRM_FORMAT_YUV420_10BIT
:
751 bytes_per_column
= 15;
753 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
754 case DRM_FORMAT_X0L2
:
756 bytes_per_column
= 8;
761 bytes_per_column
= malidpx50_get_bytes_per_column(fmt
);
764 if (bytes_per_column
== -EINVAL
)
765 return bytes_per_column
;
767 return w
* bytes_per_column
;
770 static int malidp650_rotmem_required(struct malidp_hw_device
*hwdev
, u16 w
,
771 u16 h
, u32 fmt
, bool has_modifier
)
773 int bytes_per_column
= 0;
776 /* 16 lines at 2 bytes per pixel */
777 case DRM_FORMAT_X0L2
:
778 bytes_per_column
= 32;
781 bytes_per_column
= malidpx50_get_bytes_per_column(fmt
);
784 if (bytes_per_column
== -EINVAL
)
785 return bytes_per_column
;
787 return w
* bytes_per_column
;
790 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device
*hwdev
,
791 struct malidp_se_config
*se_config
,
792 struct malidp_se_config
*old_config
)
794 u32 mask
= MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK
) |
795 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK
);
796 u32 new_value
= MALIDP550_SE_CTL_VCSEL(se_config
->vcoeff
) |
797 MALIDP550_SE_CTL_HCSEL(se_config
->hcoeff
);
799 malidp_hw_clearbits(hwdev
, mask
, MALIDP550_SE_CONTROL
);
800 malidp_hw_setbits(hwdev
, new_value
, MALIDP550_SE_CONTROL
);
804 static long malidp550_se_calc_mclk(struct malidp_hw_device
*hwdev
,
805 struct malidp_se_config
*se_config
,
806 struct videomode
*vm
)
809 unsigned long pxlclk
= vm
->pixelclock
;
810 unsigned long htotal
= vm
->hactive
+ vm
->hfront_porch
+
811 vm
->hback_porch
+ vm
->hsync_len
;
812 unsigned long numerator
= 1, denominator
= 1;
815 if (se_config
->scale_enable
) {
816 numerator
= max(se_config
->input_w
, se_config
->output_w
) *
818 numerator
+= se_config
->output_w
*
819 (se_config
->output_h
-
820 min(se_config
->input_h
, se_config
->output_h
));
821 denominator
= (htotal
- 2) * se_config
->output_h
;
824 /* mclk can't be slower than pxlclk. */
825 if (numerator
< denominator
)
826 numerator
= denominator
= 1;
827 mclk
= (pxlclk
* numerator
) / denominator
;
828 ret
= clk_get_rate(hwdev
->mclk
);
830 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
837 static int malidp550_enable_memwrite(struct malidp_hw_device
*hwdev
,
838 dma_addr_t
*addrs
, s32
*pitches
,
839 int num_planes
, u16 w
, u16 h
, u32 fmt_id
,
840 const s16
*rgb2yuv_coeffs
)
842 u32 base
= MALIDP550_SE_MEMWRITE_BASE
;
843 u32 de_base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
845 /* enable the scaling engine block */
846 malidp_hw_setbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, de_base
+ MALIDP_DE_DISPLAY_FUNC
);
848 hwdev
->mw_state
= MW_ONESHOT
;
850 malidp_hw_write(hwdev
, fmt_id
, base
+ MALIDP_MW_FORMAT
);
851 switch (num_planes
) {
853 malidp_hw_write(hwdev
, lower_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_LOW
);
854 malidp_hw_write(hwdev
, upper_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_HIGH
);
855 malidp_hw_write(hwdev
, pitches
[1], base
+ MALIDP_MW_P2_STRIDE
);
858 malidp_hw_write(hwdev
, lower_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_LOW
);
859 malidp_hw_write(hwdev
, upper_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_HIGH
);
860 malidp_hw_write(hwdev
, pitches
[0], base
+ MALIDP_MW_P1_STRIDE
);
863 WARN(1, "Invalid number of planes");
866 malidp_hw_write(hwdev
, MALIDP_DE_H_ACTIVE(w
) | MALIDP_DE_V_ACTIVE(h
),
867 MALIDP550_SE_MEMWRITE_OUT_SIZE
);
868 malidp_hw_setbits(hwdev
, MALIDP550_SE_MEMWRITE_ONESHOT
| MALIDP_SE_MEMWRITE_EN
,
869 MALIDP550_SE_CONTROL
);
871 if (rgb2yuv_coeffs
) {
874 for (i
= 0; i
< MALIDP_COLORADJ_NUM_COEFFS
; i
++) {
875 malidp_hw_write(hwdev
, rgb2yuv_coeffs
[i
],
876 MALIDP550_SE_RGB_YUV_COEFFS
+ i
* 4);
883 static void malidp550_disable_memwrite(struct malidp_hw_device
*hwdev
)
885 u32 base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
887 malidp_hw_clearbits(hwdev
, MALIDP550_SE_MEMWRITE_ONESHOT
| MALIDP_SE_MEMWRITE_EN
,
888 MALIDP550_SE_CONTROL
);
889 malidp_hw_clearbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, base
+ MALIDP_DE_DISPLAY_FUNC
);
892 static int malidp650_query_hw(struct malidp_hw_device
*hwdev
)
894 u32 conf
= malidp_hw_read(hwdev
, MALIDP550_CONFIG_ID
);
895 u8 ln_size
= (conf
>> 4) & 0x3, rsize
;
897 hwdev
->min_line_size
= 4;
902 /* reserved values */
903 hwdev
->max_line_size
= 0;
906 hwdev
->max_line_size
= SZ_4K
;
907 /* two banks of 128KB for rotation memory */
911 hwdev
->max_line_size
= 2560;
912 /* two banks of 80KB for rotation memory */
916 hwdev
->rotation_memory
[0] = hwdev
->rotation_memory
[1] = rsize
* SZ_1K
;
920 const struct malidp_hw malidp_device
[MALIDP_MAX_DEVICES
] = {
923 .coeffs_base
= MALIDP500_COEFFS_BASE
,
924 .se_base
= MALIDP500_SE_BASE
,
925 .dc_base
= MALIDP500_DC_BASE
,
926 .out_depth_base
= MALIDP500_OUTPUT_DEPTH
,
927 .features
= 0, /* no CLEARIRQ register */
928 .n_layers
= ARRAY_SIZE(malidp500_layers
),
929 .layers
= malidp500_layers
,
931 .irq_mask
= MALIDP_DE_IRQ_UNDERRUN
|
932 MALIDP500_DE_IRQ_AXI_ERR
|
933 MALIDP500_DE_IRQ_VSYNC
|
934 MALIDP500_DE_IRQ_GLOBAL
,
935 .vsync_irq
= MALIDP500_DE_IRQ_VSYNC
,
936 .err_mask
= MALIDP_DE_IRQ_UNDERRUN
|
937 MALIDP500_DE_IRQ_AXI_ERR
|
938 MALIDP500_DE_IRQ_SATURATION
,
941 .irq_mask
= MALIDP500_SE_IRQ_CONF_MODE
|
942 MALIDP500_SE_IRQ_CONF_VALID
|
943 MALIDP500_SE_IRQ_GLOBAL
,
944 .vsync_irq
= MALIDP500_SE_IRQ_CONF_VALID
,
945 .err_mask
= MALIDP500_SE_IRQ_INIT_BUSY
|
946 MALIDP500_SE_IRQ_AXI_ERROR
|
947 MALIDP500_SE_IRQ_OVERRUN
,
950 .irq_mask
= MALIDP500_DE_IRQ_CONF_VALID
,
951 .vsync_irq
= MALIDP500_DE_IRQ_CONF_VALID
,
953 .pixel_formats
= malidp500_de_formats
,
954 .n_pixel_formats
= ARRAY_SIZE(malidp500_de_formats
),
955 .bus_align_bytes
= 8,
957 .query_hw
= malidp500_query_hw
,
958 .enter_config_mode
= malidp500_enter_config_mode
,
959 .leave_config_mode
= malidp500_leave_config_mode
,
960 .in_config_mode
= malidp500_in_config_mode
,
961 .set_config_valid
= malidp500_set_config_valid
,
962 .modeset
= malidp500_modeset
,
963 .rotmem_required
= malidp500_rotmem_required
,
964 .se_set_scaling_coeffs
= malidp500_se_set_scaling_coeffs
,
965 .se_calc_mclk
= malidp500_se_calc_mclk
,
966 .enable_memwrite
= malidp500_enable_memwrite
,
967 .disable_memwrite
= malidp500_disable_memwrite
,
968 .features
= MALIDP_DEVICE_LV_HAS_3_STRIDES
,
972 .coeffs_base
= MALIDP550_COEFFS_BASE
,
973 .se_base
= MALIDP550_SE_BASE
,
974 .dc_base
= MALIDP550_DC_BASE
,
975 .out_depth_base
= MALIDP550_DE_OUTPUT_DEPTH
,
976 .features
= MALIDP_REGMAP_HAS_CLEARIRQ
|
977 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT
|
978 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT
|
979 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2
,
980 .n_layers
= ARRAY_SIZE(malidp550_layers
),
981 .layers
= malidp550_layers
,
983 .irq_mask
= MALIDP_DE_IRQ_UNDERRUN
|
984 MALIDP550_DE_IRQ_VSYNC
,
985 .vsync_irq
= MALIDP550_DE_IRQ_VSYNC
,
986 .err_mask
= MALIDP_DE_IRQ_UNDERRUN
|
987 MALIDP550_DE_IRQ_SATURATION
|
988 MALIDP550_DE_IRQ_AXI_ERR
,
991 .irq_mask
= MALIDP550_SE_IRQ_EOW
,
992 .vsync_irq
= MALIDP550_SE_IRQ_EOW
,
993 .err_mask
= MALIDP550_SE_IRQ_AXI_ERR
|
994 MALIDP550_SE_IRQ_OVR
|
995 MALIDP550_SE_IRQ_IBSY
,
998 .irq_mask
= MALIDP550_DC_IRQ_CONF_VALID
|
1000 .vsync_irq
= MALIDP550_DC_IRQ_CONF_VALID
,
1002 .pixel_formats
= malidp550_de_formats
,
1003 .n_pixel_formats
= ARRAY_SIZE(malidp550_de_formats
),
1004 .bus_align_bytes
= 8,
1006 .query_hw
= malidp550_query_hw
,
1007 .enter_config_mode
= malidp550_enter_config_mode
,
1008 .leave_config_mode
= malidp550_leave_config_mode
,
1009 .in_config_mode
= malidp550_in_config_mode
,
1010 .set_config_valid
= malidp550_set_config_valid
,
1011 .modeset
= malidp550_modeset
,
1012 .rotmem_required
= malidp550_rotmem_required
,
1013 .se_set_scaling_coeffs
= malidp550_se_set_scaling_coeffs
,
1014 .se_calc_mclk
= malidp550_se_calc_mclk
,
1015 .enable_memwrite
= malidp550_enable_memwrite
,
1016 .disable_memwrite
= malidp550_disable_memwrite
,
1021 .coeffs_base
= MALIDP550_COEFFS_BASE
,
1022 .se_base
= MALIDP550_SE_BASE
,
1023 .dc_base
= MALIDP550_DC_BASE
,
1024 .out_depth_base
= MALIDP550_DE_OUTPUT_DEPTH
,
1025 .features
= MALIDP_REGMAP_HAS_CLEARIRQ
|
1026 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT
|
1027 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2
,
1028 .n_layers
= ARRAY_SIZE(malidp650_layers
),
1029 .layers
= malidp650_layers
,
1031 .irq_mask
= MALIDP_DE_IRQ_UNDERRUN
|
1032 MALIDP650_DE_IRQ_DRIFT
|
1033 MALIDP550_DE_IRQ_VSYNC
,
1034 .vsync_irq
= MALIDP550_DE_IRQ_VSYNC
,
1035 .err_mask
= MALIDP_DE_IRQ_UNDERRUN
|
1036 MALIDP650_DE_IRQ_DRIFT
|
1037 MALIDP550_DE_IRQ_SATURATION
|
1038 MALIDP550_DE_IRQ_AXI_ERR
|
1039 MALIDP650_DE_IRQ_ACEV1
|
1040 MALIDP650_DE_IRQ_ACEV2
|
1041 MALIDP650_DE_IRQ_ACEG
|
1042 MALIDP650_DE_IRQ_AXIEP
,
1045 .irq_mask
= MALIDP550_SE_IRQ_EOW
,
1046 .vsync_irq
= MALIDP550_SE_IRQ_EOW
,
1047 .err_mask
= MALIDP550_SE_IRQ_AXI_ERR
|
1048 MALIDP550_SE_IRQ_OVR
|
1049 MALIDP550_SE_IRQ_IBSY
,
1052 .irq_mask
= MALIDP550_DC_IRQ_CONF_VALID
|
1053 MALIDP550_DC_IRQ_SE
,
1054 .vsync_irq
= MALIDP550_DC_IRQ_CONF_VALID
,
1056 .pixel_formats
= malidp650_de_formats
,
1057 .n_pixel_formats
= ARRAY_SIZE(malidp650_de_formats
),
1058 .bus_align_bytes
= 16,
1060 .query_hw
= malidp650_query_hw
,
1061 .enter_config_mode
= malidp550_enter_config_mode
,
1062 .leave_config_mode
= malidp550_leave_config_mode
,
1063 .in_config_mode
= malidp550_in_config_mode
,
1064 .set_config_valid
= malidp550_set_config_valid
,
1065 .modeset
= malidp550_modeset
,
1066 .rotmem_required
= malidp650_rotmem_required
,
1067 .se_set_scaling_coeffs
= malidp550_se_set_scaling_coeffs
,
1068 .se_calc_mclk
= malidp550_se_calc_mclk
,
1069 .enable_memwrite
= malidp550_enable_memwrite
,
1070 .disable_memwrite
= malidp550_disable_memwrite
,
1075 u8
malidp_hw_get_format_id(const struct malidp_hw_regmap
*map
,
1076 u8 layer_id
, u32 format
, bool has_modifier
)
1080 for (i
= 0; i
< map
->n_pixel_formats
; i
++) {
1081 if (((map
->pixel_formats
[i
].layer
& layer_id
) == layer_id
) &&
1082 (map
->pixel_formats
[i
].format
== format
)) {
1084 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1085 * is supported by a different h/w format id than
1086 * DRM_FORMAT_YUYV (only).
1088 if (format
== DRM_FORMAT_YUYV
&&
1090 (map
->features
& MALIDP_DEVICE_AFBC_YUYV_USE_422_P2
))
1091 return AFBC_YUV_422_FORMAT_ID
;
1093 return map
->pixel_formats
[i
].id
;
1097 return MALIDP_INVALID_FORMAT_ID
;
1100 bool malidp_hw_format_is_linear_only(u32 format
)
1103 case DRM_FORMAT_ARGB2101010
:
1104 case DRM_FORMAT_RGBA1010102
:
1105 case DRM_FORMAT_BGRA1010102
:
1106 case DRM_FORMAT_ARGB8888
:
1107 case DRM_FORMAT_RGBA8888
:
1108 case DRM_FORMAT_BGRA8888
:
1109 case DRM_FORMAT_XBGR8888
:
1110 case DRM_FORMAT_XRGB8888
:
1111 case DRM_FORMAT_RGBX8888
:
1112 case DRM_FORMAT_BGRX8888
:
1113 case DRM_FORMAT_RGB888
:
1114 case DRM_FORMAT_RGB565
:
1115 case DRM_FORMAT_ARGB1555
:
1116 case DRM_FORMAT_RGBA5551
:
1117 case DRM_FORMAT_BGRA5551
:
1118 case DRM_FORMAT_UYVY
:
1119 case DRM_FORMAT_XYUV8888
:
1120 case DRM_FORMAT_XVYU2101010
:
1121 case DRM_FORMAT_X0L2
:
1122 case DRM_FORMAT_X0L0
:
1129 bool malidp_hw_format_is_afbc_only(u32 format
)
1132 case DRM_FORMAT_VUY888
:
1133 case DRM_FORMAT_VUY101010
:
1134 case DRM_FORMAT_YUV420_8BIT
:
1135 case DRM_FORMAT_YUV420_10BIT
:
1142 static void malidp_hw_clear_irq(struct malidp_hw_device
*hwdev
, u8 block
, u32 irq
)
1144 u32 base
= malidp_get_block_base(hwdev
, block
);
1146 if (hwdev
->hw
->map
.features
& MALIDP_REGMAP_HAS_CLEARIRQ
)
1147 malidp_hw_write(hwdev
, irq
, base
+ MALIDP_REG_CLEARIRQ
);
1149 malidp_hw_write(hwdev
, irq
, base
+ MALIDP_REG_STATUS
);
1152 static irqreturn_t
malidp_de_irq(int irq
, void *arg
)
1154 struct drm_device
*drm
= arg
;
1155 struct malidp_drm
*malidp
= drm
->dev_private
;
1156 struct malidp_hw_device
*hwdev
;
1157 struct malidp_hw
*hw
;
1158 const struct malidp_irq_map
*de
;
1159 u32 status
, mask
, dc_status
;
1160 irqreturn_t ret
= IRQ_NONE
;
1162 hwdev
= malidp
->dev
;
1164 de
= &hw
->map
.de_irq_map
;
1167 * if we are suspended it is likely that we were invoked because
1168 * we share an interrupt line with some other driver, don't try
1169 * to read the hardware registers
1171 if (hwdev
->pm_suspended
)
1174 /* first handle the config valid IRQ */
1175 dc_status
= malidp_hw_read(hwdev
, hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
1176 if (dc_status
& hw
->map
.dc_irq_map
.vsync_irq
) {
1177 malidp_hw_clear_irq(hwdev
, MALIDP_DC_BLOCK
, dc_status
);
1178 /* do we have a page flip event? */
1179 if (malidp
->event
!= NULL
) {
1180 spin_lock(&drm
->event_lock
);
1181 drm_crtc_send_vblank_event(&malidp
->crtc
, malidp
->event
);
1182 malidp
->event
= NULL
;
1183 spin_unlock(&drm
->event_lock
);
1185 atomic_set(&malidp
->config_valid
, MALIDP_CONFIG_VALID_DONE
);
1186 ret
= IRQ_WAKE_THREAD
;
1189 status
= malidp_hw_read(hwdev
, MALIDP_REG_STATUS
);
1190 if (!(status
& de
->irq_mask
))
1193 mask
= malidp_hw_read(hwdev
, MALIDP_REG_MASKIRQ
);
1194 /* keep the status of the enabled interrupts, plus the error bits */
1195 status
&= (mask
| de
->err_mask
);
1196 if ((status
& de
->vsync_irq
) && malidp
->crtc
.enabled
)
1197 drm_crtc_handle_vblank(&malidp
->crtc
);
1199 #ifdef CONFIG_DEBUG_FS
1200 if (status
& de
->err_mask
) {
1201 malidp_error(malidp
, &malidp
->de_errors
, status
,
1202 drm_crtc_vblank_count(&malidp
->crtc
));
1205 malidp_hw_clear_irq(hwdev
, MALIDP_DE_BLOCK
, status
);
1207 return (ret
== IRQ_NONE
) ? IRQ_HANDLED
: ret
;
1210 static irqreturn_t
malidp_de_irq_thread_handler(int irq
, void *arg
)
1212 struct drm_device
*drm
= arg
;
1213 struct malidp_drm
*malidp
= drm
->dev_private
;
1215 wake_up(&malidp
->wq
);
1220 void malidp_de_irq_hw_init(struct malidp_hw_device
*hwdev
)
1222 /* ensure interrupts are disabled */
1223 malidp_hw_disable_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1224 malidp_hw_clear_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1225 malidp_hw_disable_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1226 malidp_hw_clear_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1228 /* first enable the DC block IRQs */
1229 malidp_hw_enable_irq(hwdev
, MALIDP_DC_BLOCK
,
1230 hwdev
->hw
->map
.dc_irq_map
.irq_mask
);
1232 /* now enable the DE block IRQs */
1233 malidp_hw_enable_irq(hwdev
, MALIDP_DE_BLOCK
,
1234 hwdev
->hw
->map
.de_irq_map
.irq_mask
);
1237 int malidp_de_irq_init(struct drm_device
*drm
, int irq
)
1239 struct malidp_drm
*malidp
= drm
->dev_private
;
1240 struct malidp_hw_device
*hwdev
= malidp
->dev
;
1243 /* ensure interrupts are disabled */
1244 malidp_hw_disable_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1245 malidp_hw_clear_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1246 malidp_hw_disable_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1247 malidp_hw_clear_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1249 ret
= devm_request_threaded_irq(drm
->dev
, irq
, malidp_de_irq
,
1250 malidp_de_irq_thread_handler
,
1251 IRQF_SHARED
, "malidp-de", drm
);
1253 DRM_ERROR("failed to install DE IRQ handler\n");
1257 malidp_de_irq_hw_init(hwdev
);
1262 void malidp_de_irq_fini(struct malidp_hw_device
*hwdev
)
1264 malidp_hw_disable_irq(hwdev
, MALIDP_DE_BLOCK
,
1265 hwdev
->hw
->map
.de_irq_map
.irq_mask
);
1266 malidp_hw_disable_irq(hwdev
, MALIDP_DC_BLOCK
,
1267 hwdev
->hw
->map
.dc_irq_map
.irq_mask
);
1270 static irqreturn_t
malidp_se_irq(int irq
, void *arg
)
1272 struct drm_device
*drm
= arg
;
1273 struct malidp_drm
*malidp
= drm
->dev_private
;
1274 struct malidp_hw_device
*hwdev
= malidp
->dev
;
1275 struct malidp_hw
*hw
= hwdev
->hw
;
1276 const struct malidp_irq_map
*se
= &hw
->map
.se_irq_map
;
1280 * if we are suspended it is likely that we were invoked because
1281 * we share an interrupt line with some other driver, don't try
1282 * to read the hardware registers
1284 if (hwdev
->pm_suspended
)
1287 status
= malidp_hw_read(hwdev
, hw
->map
.se_base
+ MALIDP_REG_STATUS
);
1288 if (!(status
& (se
->irq_mask
| se
->err_mask
)))
1291 #ifdef CONFIG_DEBUG_FS
1292 if (status
& se
->err_mask
)
1293 malidp_error(malidp
, &malidp
->se_errors
, status
,
1294 drm_crtc_vblank_count(&malidp
->crtc
));
1296 mask
= malidp_hw_read(hwdev
, hw
->map
.se_base
+ MALIDP_REG_MASKIRQ
);
1299 if (status
& se
->vsync_irq
) {
1300 switch (hwdev
->mw_state
) {
1302 drm_writeback_signal_completion(&malidp
->mw_connector
, 0);
1305 drm_writeback_signal_completion(&malidp
->mw_connector
, 0);
1306 /* disable writeback after stop */
1307 hwdev
->mw_state
= MW_NOT_ENABLED
;
1310 drm_writeback_signal_completion(&malidp
->mw_connector
, 0);
1311 /* fall through to a new start */
1313 /* writeback started, need to emulate one-shot mode */
1314 hw
->disable_memwrite(hwdev
);
1316 * only set config_valid HW bit if there is no other update
1317 * in progress or if we raced ahead of the DE IRQ handler
1318 * and config_valid flag will not be update until later
1320 status
= malidp_hw_read(hwdev
, hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
1321 if ((atomic_read(&malidp
->config_valid
) != MALIDP_CONFIG_START
) ||
1322 (status
& hw
->map
.dc_irq_map
.vsync_irq
))
1323 hw
->set_config_valid(hwdev
, 1);
1328 malidp_hw_clear_irq(hwdev
, MALIDP_SE_BLOCK
, status
);
1333 void malidp_se_irq_hw_init(struct malidp_hw_device
*hwdev
)
1335 /* ensure interrupts are disabled */
1336 malidp_hw_disable_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1337 malidp_hw_clear_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1339 malidp_hw_enable_irq(hwdev
, MALIDP_SE_BLOCK
,
1340 hwdev
->hw
->map
.se_irq_map
.irq_mask
);
1343 static irqreturn_t
malidp_se_irq_thread_handler(int irq
, void *arg
)
1348 int malidp_se_irq_init(struct drm_device
*drm
, int irq
)
1350 struct malidp_drm
*malidp
= drm
->dev_private
;
1351 struct malidp_hw_device
*hwdev
= malidp
->dev
;
1354 /* ensure interrupts are disabled */
1355 malidp_hw_disable_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1356 malidp_hw_clear_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1358 ret
= devm_request_threaded_irq(drm
->dev
, irq
, malidp_se_irq
,
1359 malidp_se_irq_thread_handler
,
1360 IRQF_SHARED
, "malidp-se", drm
);
1362 DRM_ERROR("failed to install SE IRQ handler\n");
1366 hwdev
->mw_state
= MW_NOT_ENABLED
;
1367 malidp_se_irq_hw_init(hwdev
);
1372 void malidp_se_irq_fini(struct malidp_hw_device
*hwdev
)
1374 malidp_hw_disable_irq(hwdev
, MALIDP_SE_BLOCK
,
1375 hwdev
->hw
->map
.se_irq_map
.irq_mask
);