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 const struct drm_format_info
*info
= drm_format_info(fmt
);
382 int bpp
= info
->cpp
[0] * 8;
386 case DRM_FORMAT_VUY101010
:
388 case DRM_FORMAT_YUV420_10BIT
:
391 case DRM_FORMAT_YUV420_8BIT
:
402 static int malidp500_rotmem_required(struct malidp_hw_device
*hwdev
, u16 w
,
403 u16 h
, u32 fmt
, bool has_modifier
)
406 * Each layer needs enough rotation memory to fit 8 lines
407 * worth of pixel data. Required size is then:
408 * size = rotated_width * (bpp / 8) * 8;
410 int bpp
= malidp_format_get_bpp(fmt
);
415 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device
*hwdev
,
421 u16 scaling_control
= MALIDP500_SE_CONTROL
+ MALIDP_SE_SCALING_CONTROL
;
423 malidp_hw_write(hwdev
,
424 direction
| (addr
& MALIDP_SE_COEFFTAB_ADDR_MASK
),
425 scaling_control
+ MALIDP_SE_COEFFTAB_ADDR
);
426 for (i
= 0; i
< ARRAY_SIZE(dp500_se_scaling_coeffs
); ++i
)
427 malidp_hw_write(hwdev
, MALIDP_SE_SET_COEFFTAB_DATA(
428 dp500_se_scaling_coeffs
[coeffs_id
][i
]),
429 scaling_control
+ MALIDP_SE_COEFFTAB_DATA
);
432 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device
*hwdev
,
433 struct malidp_se_config
*se_config
,
434 struct malidp_se_config
*old_config
)
436 /* Get array indices into dp500_se_scaling_coeffs. */
437 u8 h
= (u8
)se_config
->hcoeff
- 1;
438 u8 v
= (u8
)se_config
->vcoeff
- 1;
440 if (WARN_ON(h
>= ARRAY_SIZE(dp500_se_scaling_coeffs
) ||
441 v
>= ARRAY_SIZE(dp500_se_scaling_coeffs
)))
444 if ((h
== v
) && (se_config
->hcoeff
!= old_config
->hcoeff
||
445 se_config
->vcoeff
!= old_config
->vcoeff
)) {
446 malidp500_se_write_pp_coefftab(hwdev
,
447 (MALIDP_SE_V_COEFFTAB
|
448 MALIDP_SE_H_COEFFTAB
),
451 if (se_config
->vcoeff
!= old_config
->vcoeff
)
452 malidp500_se_write_pp_coefftab(hwdev
,
453 MALIDP_SE_V_COEFFTAB
,
455 if (se_config
->hcoeff
!= old_config
->hcoeff
)
456 malidp500_se_write_pp_coefftab(hwdev
,
457 MALIDP_SE_H_COEFFTAB
,
464 static long malidp500_se_calc_mclk(struct malidp_hw_device
*hwdev
,
465 struct malidp_se_config
*se_config
,
466 struct videomode
*vm
)
469 unsigned long pxlclk
= vm
->pixelclock
; /* Hz */
470 unsigned long htotal
= vm
->hactive
+ vm
->hfront_porch
+
471 vm
->hback_porch
+ vm
->hsync_len
;
472 unsigned long input_size
= se_config
->input_w
* se_config
->input_h
;
473 unsigned long a
= 10;
477 * mclk = max(a, 1.5) * pxlclk
479 * To avoid float calculaiton, using 15 instead of 1.5 and div by
482 if (se_config
->scale_enable
) {
483 a
= 15 * input_size
/ (htotal
* se_config
->output_h
);
487 mclk
= a
* pxlclk
/ 10;
488 ret
= clk_get_rate(hwdev
->mclk
);
490 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
497 static int malidp500_enable_memwrite(struct malidp_hw_device
*hwdev
,
498 dma_addr_t
*addrs
, s32
*pitches
,
499 int num_planes
, u16 w
, u16 h
, u32 fmt_id
,
500 const s16
*rgb2yuv_coeffs
)
502 u32 base
= MALIDP500_SE_MEMWRITE_BASE
;
503 u32 de_base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
505 /* enable the scaling engine block */
506 malidp_hw_setbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, de_base
+ MALIDP_DE_DISPLAY_FUNC
);
508 /* restart the writeback if already enabled */
509 if (hwdev
->mw_state
!= MW_NOT_ENABLED
)
510 hwdev
->mw_state
= MW_RESTART
;
512 hwdev
->mw_state
= MW_START
;
514 malidp_hw_write(hwdev
, fmt_id
, base
+ MALIDP_MW_FORMAT
);
515 switch (num_planes
) {
517 malidp_hw_write(hwdev
, lower_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_LOW
);
518 malidp_hw_write(hwdev
, upper_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_HIGH
);
519 malidp_hw_write(hwdev
, pitches
[1], base
+ MALIDP_MW_P2_STRIDE
);
522 malidp_hw_write(hwdev
, lower_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_LOW
);
523 malidp_hw_write(hwdev
, upper_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_HIGH
);
524 malidp_hw_write(hwdev
, pitches
[0], base
+ MALIDP_MW_P1_STRIDE
);
527 WARN(1, "Invalid number of planes");
530 malidp_hw_write(hwdev
, MALIDP_DE_H_ACTIVE(w
) | MALIDP_DE_V_ACTIVE(h
),
531 MALIDP500_SE_MEMWRITE_OUT_SIZE
);
533 if (rgb2yuv_coeffs
) {
536 for (i
= 0; i
< MALIDP_COLORADJ_NUM_COEFFS
; i
++) {
537 malidp_hw_write(hwdev
, rgb2yuv_coeffs
[i
],
538 MALIDP500_SE_RGB_YUV_COEFFS
+ i
* 4);
542 malidp_hw_setbits(hwdev
, MALIDP_SE_MEMWRITE_EN
, MALIDP500_SE_CONTROL
);
547 static void malidp500_disable_memwrite(struct malidp_hw_device
*hwdev
)
549 u32 base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
551 if (hwdev
->mw_state
== MW_START
|| hwdev
->mw_state
== MW_RESTART
)
552 hwdev
->mw_state
= MW_STOP
;
553 malidp_hw_clearbits(hwdev
, MALIDP_SE_MEMWRITE_EN
, MALIDP500_SE_CONTROL
);
554 malidp_hw_clearbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, base
+ MALIDP_DE_DISPLAY_FUNC
);
557 static int malidp550_query_hw(struct malidp_hw_device
*hwdev
)
559 u32 conf
= malidp_hw_read(hwdev
, MALIDP550_CONFIG_ID
);
560 u8 ln_size
= (conf
>> 4) & 0x3, rsize
;
562 hwdev
->min_line_size
= 2;
566 hwdev
->max_line_size
= SZ_2K
;
567 /* two banks of 64KB for rotation memory */
571 hwdev
->max_line_size
= SZ_4K
;
572 /* two banks of 128KB for rotation memory */
576 hwdev
->max_line_size
= 1280;
577 /* two banks of 40KB for rotation memory */
582 hwdev
->max_line_size
= 0;
586 hwdev
->rotation_memory
[0] = hwdev
->rotation_memory
[1] = rsize
* SZ_1K
;
590 static void malidp550_enter_config_mode(struct malidp_hw_device
*hwdev
)
592 u32 status
, count
= 100;
594 malidp_hw_setbits(hwdev
, MALIDP550_DC_CONFIG_REQ
, MALIDP550_DC_CONTROL
);
596 status
= malidp_hw_read(hwdev
, hwdev
->hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
597 if ((status
& MALIDP550_DC_CONFIG_REQ
) == MALIDP550_DC_CONFIG_REQ
)
600 * entering config mode can take as long as the rendering
601 * of a full frame, hence the long sleep here
603 usleep_range(1000, 10000);
606 WARN(count
== 0, "timeout while entering config mode");
609 static void malidp550_leave_config_mode(struct malidp_hw_device
*hwdev
)
611 u32 status
, count
= 100;
613 malidp_hw_clearbits(hwdev
, MALIDP_CFG_VALID
, MALIDP550_CONFIG_VALID
);
614 malidp_hw_clearbits(hwdev
, MALIDP550_DC_CONFIG_REQ
, MALIDP550_DC_CONTROL
);
616 status
= malidp_hw_read(hwdev
, hwdev
->hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
617 if ((status
& MALIDP550_DC_CONFIG_REQ
) == 0)
619 usleep_range(100, 1000);
622 WARN(count
== 0, "timeout while leaving config mode");
625 static bool malidp550_in_config_mode(struct malidp_hw_device
*hwdev
)
629 status
= malidp_hw_read(hwdev
, hwdev
->hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
630 if ((status
& MALIDP550_DC_CONFIG_REQ
) == MALIDP550_DC_CONFIG_REQ
)
636 static void malidp550_set_config_valid(struct malidp_hw_device
*hwdev
, u8 value
)
639 malidp_hw_setbits(hwdev
, MALIDP_CFG_VALID
, MALIDP550_CONFIG_VALID
);
641 malidp_hw_clearbits(hwdev
, MALIDP_CFG_VALID
, MALIDP550_CONFIG_VALID
);
644 static void malidp550_modeset(struct malidp_hw_device
*hwdev
, struct videomode
*mode
)
646 u32 val
= MALIDP_DE_DEFAULT_PREFETCH_START
;
648 malidp_hw_write(hwdev
, hwdev
->output_color_depth
,
649 hwdev
->hw
->map
.out_depth_base
);
650 malidp_hw_write(hwdev
, val
, MALIDP550_DE_CONTROL
);
652 * Mali-DP550 and Mali-DP650 encode the background color like this:
653 * - red @ MALIDP550_DE_BGND_COLOR[23:16]
654 * - green @ MALIDP550_DE_BGND_COLOR[15:8]
655 * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
657 * We need to truncate the least significant 4 bits from the default
658 * MALIDP_BGND_COLOR_x values
660 val
= (((MALIDP_BGND_COLOR_R
>> 4) & 0xff) << 16) |
661 (((MALIDP_BGND_COLOR_G
>> 4) & 0xff) << 8) |
662 ((MALIDP_BGND_COLOR_B
>> 4) & 0xff);
663 malidp_hw_write(hwdev
, val
, MALIDP550_DE_BGND_COLOR
);
665 val
= MALIDP_DE_H_FRONTPORCH(mode
->hfront_porch
) |
666 MALIDP_DE_H_BACKPORCH(mode
->hback_porch
);
667 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_H_TIMINGS
);
669 val
= MALIDP550_DE_V_FRONTPORCH(mode
->vfront_porch
) |
670 MALIDP_DE_V_BACKPORCH(mode
->vback_porch
);
671 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_V_TIMINGS
);
673 val
= MALIDP_DE_H_SYNCWIDTH(mode
->hsync_len
) |
674 MALIDP_DE_V_SYNCWIDTH(mode
->vsync_len
);
675 if (mode
->flags
& DISPLAY_FLAGS_HSYNC_HIGH
)
676 val
|= MALIDP550_HSYNCPOL
;
677 if (mode
->flags
& DISPLAY_FLAGS_VSYNC_HIGH
)
678 val
|= MALIDP550_VSYNCPOL
;
679 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_SYNC_WIDTH
);
681 val
= MALIDP_DE_H_ACTIVE(mode
->hactive
) | MALIDP_DE_V_ACTIVE(mode
->vactive
);
682 malidp_hw_write(hwdev
, val
, MALIDP550_TIMINGS_BASE
+ MALIDP_DE_HV_ACTIVE
);
684 if (mode
->flags
& DISPLAY_FLAGS_INTERLACED
)
685 malidp_hw_setbits(hwdev
, MALIDP_DISP_FUNC_ILACED
, MALIDP_DE_DISPLAY_FUNC
);
687 malidp_hw_clearbits(hwdev
, MALIDP_DISP_FUNC_ILACED
, MALIDP_DE_DISPLAY_FUNC
);
690 static int malidpx50_get_bytes_per_column(u32 fmt
)
692 u32 bytes_per_column
;
695 /* 8 lines at 4 bytes per pixel */
696 case DRM_FORMAT_ARGB2101010
:
697 case DRM_FORMAT_ABGR2101010
:
698 case DRM_FORMAT_RGBA1010102
:
699 case DRM_FORMAT_BGRA1010102
:
700 case DRM_FORMAT_ARGB8888
:
701 case DRM_FORMAT_ABGR8888
:
702 case DRM_FORMAT_RGBA8888
:
703 case DRM_FORMAT_BGRA8888
:
704 case DRM_FORMAT_XRGB8888
:
705 case DRM_FORMAT_XBGR8888
:
706 case DRM_FORMAT_RGBX8888
:
707 case DRM_FORMAT_BGRX8888
:
708 case DRM_FORMAT_RGB888
:
709 case DRM_FORMAT_BGR888
:
710 /* 16 lines at 2 bytes per pixel */
711 case DRM_FORMAT_RGBA5551
:
712 case DRM_FORMAT_ABGR1555
:
713 case DRM_FORMAT_RGB565
:
714 case DRM_FORMAT_BGR565
:
715 case DRM_FORMAT_UYVY
:
716 case DRM_FORMAT_YUYV
:
717 case DRM_FORMAT_X0L0
:
718 bytes_per_column
= 32;
720 /* 16 lines at 1.5 bytes per pixel */
721 case DRM_FORMAT_NV12
:
722 case DRM_FORMAT_YUV420
:
723 /* 8 lines at 3 bytes per pixel */
724 case DRM_FORMAT_VUY888
:
725 /* 16 lines at 12 bits per pixel */
726 case DRM_FORMAT_YUV420_8BIT
:
727 /* 8 lines at 3 bytes per pixel */
728 case DRM_FORMAT_P010
:
729 bytes_per_column
= 24;
731 /* 8 lines at 30 bits per pixel */
732 case DRM_FORMAT_VUY101010
:
733 /* 16 lines at 15 bits per pixel */
734 case DRM_FORMAT_YUV420_10BIT
:
735 bytes_per_column
= 30;
741 return bytes_per_column
;
744 static int malidp550_rotmem_required(struct malidp_hw_device
*hwdev
, u16 w
,
745 u16 h
, u32 fmt
, bool has_modifier
)
747 int bytes_per_column
= 0;
750 /* 8 lines at 15 bits per pixel */
751 case DRM_FORMAT_YUV420_10BIT
:
752 bytes_per_column
= 15;
754 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
755 case DRM_FORMAT_X0L2
:
757 bytes_per_column
= 8;
762 bytes_per_column
= malidpx50_get_bytes_per_column(fmt
);
765 if (bytes_per_column
== -EINVAL
)
766 return bytes_per_column
;
768 return w
* bytes_per_column
;
771 static int malidp650_rotmem_required(struct malidp_hw_device
*hwdev
, u16 w
,
772 u16 h
, u32 fmt
, bool has_modifier
)
774 int bytes_per_column
= 0;
777 /* 16 lines at 2 bytes per pixel */
778 case DRM_FORMAT_X0L2
:
779 bytes_per_column
= 32;
782 bytes_per_column
= malidpx50_get_bytes_per_column(fmt
);
785 if (bytes_per_column
== -EINVAL
)
786 return bytes_per_column
;
788 return w
* bytes_per_column
;
791 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device
*hwdev
,
792 struct malidp_se_config
*se_config
,
793 struct malidp_se_config
*old_config
)
795 u32 mask
= MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK
) |
796 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK
);
797 u32 new_value
= MALIDP550_SE_CTL_VCSEL(se_config
->vcoeff
) |
798 MALIDP550_SE_CTL_HCSEL(se_config
->hcoeff
);
800 malidp_hw_clearbits(hwdev
, mask
, MALIDP550_SE_CONTROL
);
801 malidp_hw_setbits(hwdev
, new_value
, MALIDP550_SE_CONTROL
);
805 static long malidp550_se_calc_mclk(struct malidp_hw_device
*hwdev
,
806 struct malidp_se_config
*se_config
,
807 struct videomode
*vm
)
810 unsigned long pxlclk
= vm
->pixelclock
;
811 unsigned long htotal
= vm
->hactive
+ vm
->hfront_porch
+
812 vm
->hback_porch
+ vm
->hsync_len
;
813 unsigned long numerator
= 1, denominator
= 1;
816 if (se_config
->scale_enable
) {
817 numerator
= max(se_config
->input_w
, se_config
->output_w
) *
819 numerator
+= se_config
->output_w
*
820 (se_config
->output_h
-
821 min(se_config
->input_h
, se_config
->output_h
));
822 denominator
= (htotal
- 2) * se_config
->output_h
;
825 /* mclk can't be slower than pxlclk. */
826 if (numerator
< denominator
)
827 numerator
= denominator
= 1;
828 mclk
= (pxlclk
* numerator
) / denominator
;
829 ret
= clk_get_rate(hwdev
->mclk
);
831 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
838 static int malidp550_enable_memwrite(struct malidp_hw_device
*hwdev
,
839 dma_addr_t
*addrs
, s32
*pitches
,
840 int num_planes
, u16 w
, u16 h
, u32 fmt_id
,
841 const s16
*rgb2yuv_coeffs
)
843 u32 base
= MALIDP550_SE_MEMWRITE_BASE
;
844 u32 de_base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
846 /* enable the scaling engine block */
847 malidp_hw_setbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, de_base
+ MALIDP_DE_DISPLAY_FUNC
);
849 hwdev
->mw_state
= MW_ONESHOT
;
851 malidp_hw_write(hwdev
, fmt_id
, base
+ MALIDP_MW_FORMAT
);
852 switch (num_planes
) {
854 malidp_hw_write(hwdev
, lower_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_LOW
);
855 malidp_hw_write(hwdev
, upper_32_bits(addrs
[1]), base
+ MALIDP_MW_P2_PTR_HIGH
);
856 malidp_hw_write(hwdev
, pitches
[1], base
+ MALIDP_MW_P2_STRIDE
);
859 malidp_hw_write(hwdev
, lower_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_LOW
);
860 malidp_hw_write(hwdev
, upper_32_bits(addrs
[0]), base
+ MALIDP_MW_P1_PTR_HIGH
);
861 malidp_hw_write(hwdev
, pitches
[0], base
+ MALIDP_MW_P1_STRIDE
);
864 WARN(1, "Invalid number of planes");
867 malidp_hw_write(hwdev
, MALIDP_DE_H_ACTIVE(w
) | MALIDP_DE_V_ACTIVE(h
),
868 MALIDP550_SE_MEMWRITE_OUT_SIZE
);
869 malidp_hw_setbits(hwdev
, MALIDP550_SE_MEMWRITE_ONESHOT
| MALIDP_SE_MEMWRITE_EN
,
870 MALIDP550_SE_CONTROL
);
872 if (rgb2yuv_coeffs
) {
875 for (i
= 0; i
< MALIDP_COLORADJ_NUM_COEFFS
; i
++) {
876 malidp_hw_write(hwdev
, rgb2yuv_coeffs
[i
],
877 MALIDP550_SE_RGB_YUV_COEFFS
+ i
* 4);
884 static void malidp550_disable_memwrite(struct malidp_hw_device
*hwdev
)
886 u32 base
= malidp_get_block_base(hwdev
, MALIDP_DE_BLOCK
);
888 malidp_hw_clearbits(hwdev
, MALIDP550_SE_MEMWRITE_ONESHOT
| MALIDP_SE_MEMWRITE_EN
,
889 MALIDP550_SE_CONTROL
);
890 malidp_hw_clearbits(hwdev
, MALIDP_SCALE_ENGINE_EN
, base
+ MALIDP_DE_DISPLAY_FUNC
);
893 static int malidp650_query_hw(struct malidp_hw_device
*hwdev
)
895 u32 conf
= malidp_hw_read(hwdev
, MALIDP550_CONFIG_ID
);
896 u8 ln_size
= (conf
>> 4) & 0x3, rsize
;
898 hwdev
->min_line_size
= 4;
903 /* reserved values */
904 hwdev
->max_line_size
= 0;
907 hwdev
->max_line_size
= SZ_4K
;
908 /* two banks of 128KB for rotation memory */
912 hwdev
->max_line_size
= 2560;
913 /* two banks of 80KB for rotation memory */
917 hwdev
->rotation_memory
[0] = hwdev
->rotation_memory
[1] = rsize
* SZ_1K
;
921 const struct malidp_hw malidp_device
[MALIDP_MAX_DEVICES
] = {
924 .coeffs_base
= MALIDP500_COEFFS_BASE
,
925 .se_base
= MALIDP500_SE_BASE
,
926 .dc_base
= MALIDP500_DC_BASE
,
927 .out_depth_base
= MALIDP500_OUTPUT_DEPTH
,
928 .features
= 0, /* no CLEARIRQ register */
929 .n_layers
= ARRAY_SIZE(malidp500_layers
),
930 .layers
= malidp500_layers
,
932 .irq_mask
= MALIDP_DE_IRQ_UNDERRUN
|
933 MALIDP500_DE_IRQ_AXI_ERR
|
934 MALIDP500_DE_IRQ_VSYNC
|
935 MALIDP500_DE_IRQ_GLOBAL
,
936 .vsync_irq
= MALIDP500_DE_IRQ_VSYNC
,
937 .err_mask
= MALIDP_DE_IRQ_UNDERRUN
|
938 MALIDP500_DE_IRQ_AXI_ERR
|
939 MALIDP500_DE_IRQ_SATURATION
,
942 .irq_mask
= MALIDP500_SE_IRQ_CONF_MODE
|
943 MALIDP500_SE_IRQ_CONF_VALID
|
944 MALIDP500_SE_IRQ_GLOBAL
,
945 .vsync_irq
= MALIDP500_SE_IRQ_CONF_VALID
,
946 .err_mask
= MALIDP500_SE_IRQ_INIT_BUSY
|
947 MALIDP500_SE_IRQ_AXI_ERROR
|
948 MALIDP500_SE_IRQ_OVERRUN
,
951 .irq_mask
= MALIDP500_DE_IRQ_CONF_VALID
,
952 .vsync_irq
= MALIDP500_DE_IRQ_CONF_VALID
,
954 .pixel_formats
= malidp500_de_formats
,
955 .n_pixel_formats
= ARRAY_SIZE(malidp500_de_formats
),
956 .bus_align_bytes
= 8,
958 .query_hw
= malidp500_query_hw
,
959 .enter_config_mode
= malidp500_enter_config_mode
,
960 .leave_config_mode
= malidp500_leave_config_mode
,
961 .in_config_mode
= malidp500_in_config_mode
,
962 .set_config_valid
= malidp500_set_config_valid
,
963 .modeset
= malidp500_modeset
,
964 .rotmem_required
= malidp500_rotmem_required
,
965 .se_set_scaling_coeffs
= malidp500_se_set_scaling_coeffs
,
966 .se_calc_mclk
= malidp500_se_calc_mclk
,
967 .enable_memwrite
= malidp500_enable_memwrite
,
968 .disable_memwrite
= malidp500_disable_memwrite
,
969 .features
= MALIDP_DEVICE_LV_HAS_3_STRIDES
,
973 .coeffs_base
= MALIDP550_COEFFS_BASE
,
974 .se_base
= MALIDP550_SE_BASE
,
975 .dc_base
= MALIDP550_DC_BASE
,
976 .out_depth_base
= MALIDP550_DE_OUTPUT_DEPTH
,
977 .features
= MALIDP_REGMAP_HAS_CLEARIRQ
|
978 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT
|
979 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT
|
980 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2
,
981 .n_layers
= ARRAY_SIZE(malidp550_layers
),
982 .layers
= malidp550_layers
,
984 .irq_mask
= MALIDP_DE_IRQ_UNDERRUN
|
985 MALIDP550_DE_IRQ_VSYNC
,
986 .vsync_irq
= MALIDP550_DE_IRQ_VSYNC
,
987 .err_mask
= MALIDP_DE_IRQ_UNDERRUN
|
988 MALIDP550_DE_IRQ_SATURATION
|
989 MALIDP550_DE_IRQ_AXI_ERR
,
992 .irq_mask
= MALIDP550_SE_IRQ_EOW
,
993 .vsync_irq
= MALIDP550_SE_IRQ_EOW
,
994 .err_mask
= MALIDP550_SE_IRQ_AXI_ERR
|
995 MALIDP550_SE_IRQ_OVR
|
996 MALIDP550_SE_IRQ_IBSY
,
999 .irq_mask
= MALIDP550_DC_IRQ_CONF_VALID
|
1000 MALIDP550_DC_IRQ_SE
,
1001 .vsync_irq
= MALIDP550_DC_IRQ_CONF_VALID
,
1003 .pixel_formats
= malidp550_de_formats
,
1004 .n_pixel_formats
= ARRAY_SIZE(malidp550_de_formats
),
1005 .bus_align_bytes
= 8,
1007 .query_hw
= malidp550_query_hw
,
1008 .enter_config_mode
= malidp550_enter_config_mode
,
1009 .leave_config_mode
= malidp550_leave_config_mode
,
1010 .in_config_mode
= malidp550_in_config_mode
,
1011 .set_config_valid
= malidp550_set_config_valid
,
1012 .modeset
= malidp550_modeset
,
1013 .rotmem_required
= malidp550_rotmem_required
,
1014 .se_set_scaling_coeffs
= malidp550_se_set_scaling_coeffs
,
1015 .se_calc_mclk
= malidp550_se_calc_mclk
,
1016 .enable_memwrite
= malidp550_enable_memwrite
,
1017 .disable_memwrite
= malidp550_disable_memwrite
,
1022 .coeffs_base
= MALIDP550_COEFFS_BASE
,
1023 .se_base
= MALIDP550_SE_BASE
,
1024 .dc_base
= MALIDP550_DC_BASE
,
1025 .out_depth_base
= MALIDP550_DE_OUTPUT_DEPTH
,
1026 .features
= MALIDP_REGMAP_HAS_CLEARIRQ
|
1027 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT
|
1028 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2
,
1029 .n_layers
= ARRAY_SIZE(malidp650_layers
),
1030 .layers
= malidp650_layers
,
1032 .irq_mask
= MALIDP_DE_IRQ_UNDERRUN
|
1033 MALIDP650_DE_IRQ_DRIFT
|
1034 MALIDP550_DE_IRQ_VSYNC
,
1035 .vsync_irq
= MALIDP550_DE_IRQ_VSYNC
,
1036 .err_mask
= MALIDP_DE_IRQ_UNDERRUN
|
1037 MALIDP650_DE_IRQ_DRIFT
|
1038 MALIDP550_DE_IRQ_SATURATION
|
1039 MALIDP550_DE_IRQ_AXI_ERR
|
1040 MALIDP650_DE_IRQ_ACEV1
|
1041 MALIDP650_DE_IRQ_ACEV2
|
1042 MALIDP650_DE_IRQ_ACEG
|
1043 MALIDP650_DE_IRQ_AXIEP
,
1046 .irq_mask
= MALIDP550_SE_IRQ_EOW
,
1047 .vsync_irq
= MALIDP550_SE_IRQ_EOW
,
1048 .err_mask
= MALIDP550_SE_IRQ_AXI_ERR
|
1049 MALIDP550_SE_IRQ_OVR
|
1050 MALIDP550_SE_IRQ_IBSY
,
1053 .irq_mask
= MALIDP550_DC_IRQ_CONF_VALID
|
1054 MALIDP550_DC_IRQ_SE
,
1055 .vsync_irq
= MALIDP550_DC_IRQ_CONF_VALID
,
1057 .pixel_formats
= malidp650_de_formats
,
1058 .n_pixel_formats
= ARRAY_SIZE(malidp650_de_formats
),
1059 .bus_align_bytes
= 16,
1061 .query_hw
= malidp650_query_hw
,
1062 .enter_config_mode
= malidp550_enter_config_mode
,
1063 .leave_config_mode
= malidp550_leave_config_mode
,
1064 .in_config_mode
= malidp550_in_config_mode
,
1065 .set_config_valid
= malidp550_set_config_valid
,
1066 .modeset
= malidp550_modeset
,
1067 .rotmem_required
= malidp650_rotmem_required
,
1068 .se_set_scaling_coeffs
= malidp550_se_set_scaling_coeffs
,
1069 .se_calc_mclk
= malidp550_se_calc_mclk
,
1070 .enable_memwrite
= malidp550_enable_memwrite
,
1071 .disable_memwrite
= malidp550_disable_memwrite
,
1076 u8
malidp_hw_get_format_id(const struct malidp_hw_regmap
*map
,
1077 u8 layer_id
, u32 format
, bool has_modifier
)
1081 for (i
= 0; i
< map
->n_pixel_formats
; i
++) {
1082 if (((map
->pixel_formats
[i
].layer
& layer_id
) == layer_id
) &&
1083 (map
->pixel_formats
[i
].format
== format
)) {
1085 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1086 * is supported by a different h/w format id than
1087 * DRM_FORMAT_YUYV (only).
1089 if (format
== DRM_FORMAT_YUYV
&&
1091 (map
->features
& MALIDP_DEVICE_AFBC_YUYV_USE_422_P2
))
1092 return AFBC_YUV_422_FORMAT_ID
;
1094 return map
->pixel_formats
[i
].id
;
1098 return MALIDP_INVALID_FORMAT_ID
;
1101 bool malidp_hw_format_is_linear_only(u32 format
)
1104 case DRM_FORMAT_ARGB2101010
:
1105 case DRM_FORMAT_RGBA1010102
:
1106 case DRM_FORMAT_BGRA1010102
:
1107 case DRM_FORMAT_ARGB8888
:
1108 case DRM_FORMAT_RGBA8888
:
1109 case DRM_FORMAT_BGRA8888
:
1110 case DRM_FORMAT_XBGR8888
:
1111 case DRM_FORMAT_XRGB8888
:
1112 case DRM_FORMAT_RGBX8888
:
1113 case DRM_FORMAT_BGRX8888
:
1114 case DRM_FORMAT_RGB888
:
1115 case DRM_FORMAT_RGB565
:
1116 case DRM_FORMAT_ARGB1555
:
1117 case DRM_FORMAT_RGBA5551
:
1118 case DRM_FORMAT_BGRA5551
:
1119 case DRM_FORMAT_UYVY
:
1120 case DRM_FORMAT_XYUV8888
:
1121 case DRM_FORMAT_XVYU2101010
:
1122 case DRM_FORMAT_X0L2
:
1123 case DRM_FORMAT_X0L0
:
1130 bool malidp_hw_format_is_afbc_only(u32 format
)
1133 case DRM_FORMAT_VUY888
:
1134 case DRM_FORMAT_VUY101010
:
1135 case DRM_FORMAT_YUV420_8BIT
:
1136 case DRM_FORMAT_YUV420_10BIT
:
1143 static void malidp_hw_clear_irq(struct malidp_hw_device
*hwdev
, u8 block
, u32 irq
)
1145 u32 base
= malidp_get_block_base(hwdev
, block
);
1147 if (hwdev
->hw
->map
.features
& MALIDP_REGMAP_HAS_CLEARIRQ
)
1148 malidp_hw_write(hwdev
, irq
, base
+ MALIDP_REG_CLEARIRQ
);
1150 malidp_hw_write(hwdev
, irq
, base
+ MALIDP_REG_STATUS
);
1153 static irqreturn_t
malidp_de_irq(int irq
, void *arg
)
1155 struct drm_device
*drm
= arg
;
1156 struct malidp_drm
*malidp
= drm
->dev_private
;
1157 struct malidp_hw_device
*hwdev
;
1158 struct malidp_hw
*hw
;
1159 const struct malidp_irq_map
*de
;
1160 u32 status
, mask
, dc_status
;
1161 irqreturn_t ret
= IRQ_NONE
;
1163 hwdev
= malidp
->dev
;
1165 de
= &hw
->map
.de_irq_map
;
1168 * if we are suspended it is likely that we were invoked because
1169 * we share an interrupt line with some other driver, don't try
1170 * to read the hardware registers
1172 if (hwdev
->pm_suspended
)
1175 /* first handle the config valid IRQ */
1176 dc_status
= malidp_hw_read(hwdev
, hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
1177 if (dc_status
& hw
->map
.dc_irq_map
.vsync_irq
) {
1178 malidp_hw_clear_irq(hwdev
, MALIDP_DC_BLOCK
, dc_status
);
1179 /* do we have a page flip event? */
1180 if (malidp
->event
!= NULL
) {
1181 spin_lock(&drm
->event_lock
);
1182 drm_crtc_send_vblank_event(&malidp
->crtc
, malidp
->event
);
1183 malidp
->event
= NULL
;
1184 spin_unlock(&drm
->event_lock
);
1186 atomic_set(&malidp
->config_valid
, MALIDP_CONFIG_VALID_DONE
);
1187 ret
= IRQ_WAKE_THREAD
;
1190 status
= malidp_hw_read(hwdev
, MALIDP_REG_STATUS
);
1191 if (!(status
& de
->irq_mask
))
1194 mask
= malidp_hw_read(hwdev
, MALIDP_REG_MASKIRQ
);
1195 /* keep the status of the enabled interrupts, plus the error bits */
1196 status
&= (mask
| de
->err_mask
);
1197 if ((status
& de
->vsync_irq
) && malidp
->crtc
.enabled
)
1198 drm_crtc_handle_vblank(&malidp
->crtc
);
1200 #ifdef CONFIG_DEBUG_FS
1201 if (status
& de
->err_mask
) {
1202 malidp_error(malidp
, &malidp
->de_errors
, status
,
1203 drm_crtc_vblank_count(&malidp
->crtc
));
1206 malidp_hw_clear_irq(hwdev
, MALIDP_DE_BLOCK
, status
);
1208 return (ret
== IRQ_NONE
) ? IRQ_HANDLED
: ret
;
1211 static irqreturn_t
malidp_de_irq_thread_handler(int irq
, void *arg
)
1213 struct drm_device
*drm
= arg
;
1214 struct malidp_drm
*malidp
= drm
->dev_private
;
1216 wake_up(&malidp
->wq
);
1221 void malidp_de_irq_hw_init(struct malidp_hw_device
*hwdev
)
1223 /* ensure interrupts are disabled */
1224 malidp_hw_disable_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1225 malidp_hw_clear_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1226 malidp_hw_disable_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1227 malidp_hw_clear_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1229 /* first enable the DC block IRQs */
1230 malidp_hw_enable_irq(hwdev
, MALIDP_DC_BLOCK
,
1231 hwdev
->hw
->map
.dc_irq_map
.irq_mask
);
1233 /* now enable the DE block IRQs */
1234 malidp_hw_enable_irq(hwdev
, MALIDP_DE_BLOCK
,
1235 hwdev
->hw
->map
.de_irq_map
.irq_mask
);
1238 int malidp_de_irq_init(struct drm_device
*drm
, int irq
)
1240 struct malidp_drm
*malidp
= drm
->dev_private
;
1241 struct malidp_hw_device
*hwdev
= malidp
->dev
;
1244 /* ensure interrupts are disabled */
1245 malidp_hw_disable_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1246 malidp_hw_clear_irq(hwdev
, MALIDP_DE_BLOCK
, 0xffffffff);
1247 malidp_hw_disable_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1248 malidp_hw_clear_irq(hwdev
, MALIDP_DC_BLOCK
, 0xffffffff);
1250 ret
= devm_request_threaded_irq(drm
->dev
, irq
, malidp_de_irq
,
1251 malidp_de_irq_thread_handler
,
1252 IRQF_SHARED
, "malidp-de", drm
);
1254 DRM_ERROR("failed to install DE IRQ handler\n");
1258 malidp_de_irq_hw_init(hwdev
);
1263 void malidp_de_irq_fini(struct malidp_hw_device
*hwdev
)
1265 malidp_hw_disable_irq(hwdev
, MALIDP_DE_BLOCK
,
1266 hwdev
->hw
->map
.de_irq_map
.irq_mask
);
1267 malidp_hw_disable_irq(hwdev
, MALIDP_DC_BLOCK
,
1268 hwdev
->hw
->map
.dc_irq_map
.irq_mask
);
1271 static irqreturn_t
malidp_se_irq(int irq
, void *arg
)
1273 struct drm_device
*drm
= arg
;
1274 struct malidp_drm
*malidp
= drm
->dev_private
;
1275 struct malidp_hw_device
*hwdev
= malidp
->dev
;
1276 struct malidp_hw
*hw
= hwdev
->hw
;
1277 const struct malidp_irq_map
*se
= &hw
->map
.se_irq_map
;
1281 * if we are suspended it is likely that we were invoked because
1282 * we share an interrupt line with some other driver, don't try
1283 * to read the hardware registers
1285 if (hwdev
->pm_suspended
)
1288 status
= malidp_hw_read(hwdev
, hw
->map
.se_base
+ MALIDP_REG_STATUS
);
1289 if (!(status
& (se
->irq_mask
| se
->err_mask
)))
1292 #ifdef CONFIG_DEBUG_FS
1293 if (status
& se
->err_mask
)
1294 malidp_error(malidp
, &malidp
->se_errors
, status
,
1295 drm_crtc_vblank_count(&malidp
->crtc
));
1297 mask
= malidp_hw_read(hwdev
, hw
->map
.se_base
+ MALIDP_REG_MASKIRQ
);
1300 if (status
& se
->vsync_irq
) {
1301 switch (hwdev
->mw_state
) {
1303 drm_writeback_signal_completion(&malidp
->mw_connector
, 0);
1306 drm_writeback_signal_completion(&malidp
->mw_connector
, 0);
1307 /* disable writeback after stop */
1308 hwdev
->mw_state
= MW_NOT_ENABLED
;
1311 drm_writeback_signal_completion(&malidp
->mw_connector
, 0);
1312 /* fall through to a new start */
1314 /* writeback started, need to emulate one-shot mode */
1315 hw
->disable_memwrite(hwdev
);
1317 * only set config_valid HW bit if there is no other update
1318 * in progress or if we raced ahead of the DE IRQ handler
1319 * and config_valid flag will not be update until later
1321 status
= malidp_hw_read(hwdev
, hw
->map
.dc_base
+ MALIDP_REG_STATUS
);
1322 if ((atomic_read(&malidp
->config_valid
) != MALIDP_CONFIG_START
) ||
1323 (status
& hw
->map
.dc_irq_map
.vsync_irq
))
1324 hw
->set_config_valid(hwdev
, 1);
1329 malidp_hw_clear_irq(hwdev
, MALIDP_SE_BLOCK
, status
);
1334 void malidp_se_irq_hw_init(struct malidp_hw_device
*hwdev
)
1336 /* ensure interrupts are disabled */
1337 malidp_hw_disable_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1338 malidp_hw_clear_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1340 malidp_hw_enable_irq(hwdev
, MALIDP_SE_BLOCK
,
1341 hwdev
->hw
->map
.se_irq_map
.irq_mask
);
1344 static irqreturn_t
malidp_se_irq_thread_handler(int irq
, void *arg
)
1349 int malidp_se_irq_init(struct drm_device
*drm
, int irq
)
1351 struct malidp_drm
*malidp
= drm
->dev_private
;
1352 struct malidp_hw_device
*hwdev
= malidp
->dev
;
1355 /* ensure interrupts are disabled */
1356 malidp_hw_disable_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1357 malidp_hw_clear_irq(hwdev
, MALIDP_SE_BLOCK
, 0xffffffff);
1359 ret
= devm_request_threaded_irq(drm
->dev
, irq
, malidp_se_irq
,
1360 malidp_se_irq_thread_handler
,
1361 IRQF_SHARED
, "malidp-se", drm
);
1363 DRM_ERROR("failed to install SE IRQ handler\n");
1367 hwdev
->mw_state
= MW_NOT_ENABLED
;
1368 malidp_se_irq_hw_init(hwdev
);
1373 void malidp_se_irq_fini(struct malidp_hw_device
*hwdev
)
1375 malidp_hw_disable_irq(hwdev
, MALIDP_SE_BLOCK
,
1376 hwdev
->hw
->map
.se_irq_map
.irq_mask
);