1 // SPDX-License-Identifier: GPL-2.0-only
3 * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
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/delay.h>
13 #include <linux/types.h>
16 #include <video/videomode.h>
17 #include <video/display_timing.h>
19 #include <drm/drm_fourcc.h>
20 #include <drm/drm_vblank.h>
21 #include <drm/drm_print.h>
23 #include "malidp_drv.h"
24 #include "malidp_hw.h"
25 #include "malidp_mw.h"
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 */
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 }
61 #define MALIDP_ID(__group, __format) \
62 ((((__group) & 0x7) << 3) | ((__format) & 0x7))
64 #define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
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)}
106 static const struct malidp_format_id malidp550_de_formats[] = {
107 MALIDP_COMMON_FORMATS,
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)},
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
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 },
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
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 },
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,
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,
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),
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),
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),
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),
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),
189 DRM_FORMAT_MOD_LINEAR,
191 DRM_FORMAT_MOD_INVALID
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
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
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
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
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
268 #define MALIDP_DE_DEFAULT_PREFETCH_START 5
270 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
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;
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 */
284 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
286 u32 status, count = 100;
288 malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
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)
294 * entering config mode can take as long as the rendering
295 * of a full frame, hence the long sleep here
297 usleep_range(1000, 10000);
300 WARN(count == 0, "timeout while entering config mode");
303 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
305 u32 status, count = 100;
307 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
308 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
310 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
311 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
313 usleep_range(100, 1000);
316 WARN(count == 0, "timeout while leaving config mode");
319 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
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)
330 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
333 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
335 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
338 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
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);
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]
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);
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);
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);
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);
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);
378 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
379 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
381 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
384 int malidp_format_get_bpp(u32 fmt)
386 const struct drm_format_info *info = drm_format_info(fmt);
387 int bpp = info->cpp[0] * 8;
391 case DRM_FORMAT_VUY101010:
394 case DRM_FORMAT_YUV420_10BIT:
397 case DRM_FORMAT_YUV420_8BIT:
408 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
409 u16 h, u32 fmt, bool has_modifier)
412 * Each layer needs enough rotation memory to fit 8 lines
413 * worth of pixel data. Required size is then:
414 * size = rotated_width * (bpp / 8) * 8;
416 int bpp = malidp_format_get_bpp(fmt);
421 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
427 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
429 malidp_hw_write(hwdev,
430 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
431 scaling_control + MALIDP_SE_COEFFTAB_ADDR);
432 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
433 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
434 dp500_se_scaling_coeffs[coeffs_id][i]),
435 scaling_control + MALIDP_SE_COEFFTAB_DATA);
438 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
439 struct malidp_se_config *se_config,
440 struct malidp_se_config *old_config)
442 /* Get array indices into dp500_se_scaling_coeffs. */
443 u8 h = (u8)se_config->hcoeff - 1;
444 u8 v = (u8)se_config->vcoeff - 1;
446 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
447 v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
450 if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
451 se_config->vcoeff != old_config->vcoeff)) {
452 malidp500_se_write_pp_coefftab(hwdev,
453 (MALIDP_SE_V_COEFFTAB |
454 MALIDP_SE_H_COEFFTAB),
457 if (se_config->vcoeff != old_config->vcoeff)
458 malidp500_se_write_pp_coefftab(hwdev,
459 MALIDP_SE_V_COEFFTAB,
461 if (se_config->hcoeff != old_config->hcoeff)
462 malidp500_se_write_pp_coefftab(hwdev,
463 MALIDP_SE_H_COEFFTAB,
470 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
471 struct malidp_se_config *se_config,
472 struct videomode *vm)
475 unsigned long pxlclk = vm->pixelclock; /* Hz */
476 unsigned long htotal = vm->hactive + vm->hfront_porch +
477 vm->hback_porch + vm->hsync_len;
478 unsigned long input_size = se_config->input_w * se_config->input_h;
479 unsigned long a = 10;
483 * mclk = max(a, 1.5) * pxlclk
485 * To avoid float calculaiton, using 15 instead of 1.5 and div by
488 if (se_config->scale_enable) {
489 a = 15 * input_size / (htotal * se_config->output_h);
493 mclk = a * pxlclk / 10;
494 ret = clk_get_rate(hwdev->mclk);
496 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
503 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
504 dma_addr_t *addrs, s32 *pitches,
505 int num_planes, u16 w, u16 h, u32 fmt_id,
506 const s16 *rgb2yuv_coeffs)
508 u32 base = MALIDP500_SE_MEMWRITE_BASE;
509 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
511 /* enable the scaling engine block */
512 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
514 /* restart the writeback if already enabled */
515 if (hwdev->mw_state != MW_NOT_ENABLED)
516 hwdev->mw_state = MW_RESTART;
518 hwdev->mw_state = MW_START;
520 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
521 switch (num_planes) {
523 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
524 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
525 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
528 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
529 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
530 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
533 WARN(1, "Invalid number of planes");
536 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
537 MALIDP500_SE_MEMWRITE_OUT_SIZE);
539 if (rgb2yuv_coeffs) {
542 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
543 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
544 MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
548 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
553 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
555 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
557 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
558 hwdev->mw_state = MW_STOP;
559 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
560 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
563 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
565 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
566 u8 ln_size = (conf >> 4) & 0x3, rsize;
568 hwdev->min_line_size = 2;
572 hwdev->max_line_size = SZ_2K;
573 /* two banks of 64KB for rotation memory */
577 hwdev->max_line_size = SZ_4K;
578 /* two banks of 128KB for rotation memory */
582 hwdev->max_line_size = 1280;
583 /* two banks of 40KB for rotation memory */
588 hwdev->max_line_size = 0;
592 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
596 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
598 u32 status, count = 100;
600 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
602 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
603 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
606 * entering config mode can take as long as the rendering
607 * of a full frame, hence the long sleep here
609 usleep_range(1000, 10000);
612 WARN(count == 0, "timeout while entering config mode");
615 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
617 u32 status, count = 100;
619 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
620 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
622 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
623 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
625 usleep_range(100, 1000);
628 WARN(count == 0, "timeout while leaving config mode");
631 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
635 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
636 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
642 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
645 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
647 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
650 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
652 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
654 malidp_hw_write(hwdev, hwdev->output_color_depth,
655 hwdev->hw->map.out_depth_base);
656 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
658 * Mali-DP550 and Mali-DP650 encode the background color like this:
659 * - red @ MALIDP550_DE_BGND_COLOR[23:16]
660 * - green @ MALIDP550_DE_BGND_COLOR[15:8]
661 * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
663 * We need to truncate the least significant 4 bits from the default
664 * MALIDP_BGND_COLOR_x values
666 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
667 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
668 ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
669 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
671 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
672 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
673 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
675 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
676 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
677 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
679 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
680 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
681 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
682 val |= MALIDP550_HSYNCPOL;
683 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
684 val |= MALIDP550_VSYNCPOL;
685 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
687 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
688 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
690 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
691 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
693 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
696 static int malidpx50_get_bytes_per_column(u32 fmt)
698 u32 bytes_per_column;
701 /* 8 lines at 4 bytes per pixel */
702 case DRM_FORMAT_ARGB2101010:
703 case DRM_FORMAT_ABGR2101010:
704 case DRM_FORMAT_RGBA1010102:
705 case DRM_FORMAT_BGRA1010102:
706 case DRM_FORMAT_ARGB8888:
707 case DRM_FORMAT_ABGR8888:
708 case DRM_FORMAT_RGBA8888:
709 case DRM_FORMAT_BGRA8888:
710 case DRM_FORMAT_XRGB8888:
711 case DRM_FORMAT_XBGR8888:
712 case DRM_FORMAT_RGBX8888:
713 case DRM_FORMAT_BGRX8888:
714 case DRM_FORMAT_RGB888:
715 case DRM_FORMAT_BGR888:
716 /* 16 lines at 2 bytes per pixel */
717 case DRM_FORMAT_RGBA5551:
718 case DRM_FORMAT_ABGR1555:
719 case DRM_FORMAT_RGB565:
720 case DRM_FORMAT_BGR565:
721 case DRM_FORMAT_UYVY:
722 case DRM_FORMAT_YUYV:
723 case DRM_FORMAT_X0L0:
724 bytes_per_column = 32;
726 /* 16 lines at 1.5 bytes per pixel */
727 case DRM_FORMAT_NV12:
728 case DRM_FORMAT_YUV420:
729 /* 8 lines at 3 bytes per pixel */
730 case DRM_FORMAT_VUY888:
731 /* 16 lines at 12 bits per pixel */
732 case DRM_FORMAT_YUV420_8BIT:
733 /* 8 lines at 3 bytes per pixel */
734 case DRM_FORMAT_P010:
735 bytes_per_column = 24;
737 /* 8 lines at 30 bits per pixel */
738 case DRM_FORMAT_VUY101010:
739 /* 16 lines at 15 bits per pixel */
740 case DRM_FORMAT_YUV420_10BIT:
741 bytes_per_column = 30;
747 return bytes_per_column;
750 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
751 u16 h, u32 fmt, bool has_modifier)
753 int bytes_per_column = 0;
756 /* 8 lines at 15 bits per pixel */
757 case DRM_FORMAT_YUV420_10BIT:
758 bytes_per_column = 15;
760 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
761 case DRM_FORMAT_X0L2:
763 bytes_per_column = 8;
768 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
771 if (bytes_per_column == -EINVAL)
772 return bytes_per_column;
774 return w * bytes_per_column;
777 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
778 u16 h, u32 fmt, bool has_modifier)
780 int bytes_per_column = 0;
783 /* 16 lines at 2 bytes per pixel */
784 case DRM_FORMAT_X0L2:
785 bytes_per_column = 32;
788 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
791 if (bytes_per_column == -EINVAL)
792 return bytes_per_column;
794 return w * bytes_per_column;
797 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
798 struct malidp_se_config *se_config,
799 struct malidp_se_config *old_config)
801 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
802 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
803 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
804 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
806 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
807 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
811 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
812 struct malidp_se_config *se_config,
813 struct videomode *vm)
816 unsigned long pxlclk = vm->pixelclock;
817 unsigned long htotal = vm->hactive + vm->hfront_porch +
818 vm->hback_porch + vm->hsync_len;
819 unsigned long numerator = 1, denominator = 1;
822 if (se_config->scale_enable) {
823 numerator = max(se_config->input_w, se_config->output_w) *
825 numerator += se_config->output_w *
826 (se_config->output_h -
827 min(se_config->input_h, se_config->output_h));
828 denominator = (htotal - 2) * se_config->output_h;
831 /* mclk can't be slower than pxlclk. */
832 if (numerator < denominator)
833 numerator = denominator = 1;
834 mclk = (pxlclk * numerator) / denominator;
835 ret = clk_get_rate(hwdev->mclk);
837 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
844 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
845 dma_addr_t *addrs, s32 *pitches,
846 int num_planes, u16 w, u16 h, u32 fmt_id,
847 const s16 *rgb2yuv_coeffs)
849 u32 base = MALIDP550_SE_MEMWRITE_BASE;
850 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
852 /* enable the scaling engine block */
853 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
855 hwdev->mw_state = MW_ONESHOT;
857 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
858 switch (num_planes) {
860 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
861 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
862 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
865 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
866 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
867 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
870 WARN(1, "Invalid number of planes");
873 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
874 MALIDP550_SE_MEMWRITE_OUT_SIZE);
875 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
876 MALIDP550_SE_CONTROL);
878 if (rgb2yuv_coeffs) {
881 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
882 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
883 MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
890 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
892 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
894 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
895 MALIDP550_SE_CONTROL);
896 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
899 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
901 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
902 u8 ln_size = (conf >> 4) & 0x3, rsize;
904 hwdev->min_line_size = 4;
909 /* reserved values */
910 hwdev->max_line_size = 0;
913 hwdev->max_line_size = SZ_4K;
914 /* two banks of 128KB for rotation memory */
918 hwdev->max_line_size = 2560;
919 /* two banks of 80KB for rotation memory */
923 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
927 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
930 .coeffs_base = MALIDP500_COEFFS_BASE,
931 .se_base = MALIDP500_SE_BASE,
932 .dc_base = MALIDP500_DC_BASE,
933 .out_depth_base = MALIDP500_OUTPUT_DEPTH,
934 .features = 0, /* no CLEARIRQ register */
935 .n_layers = ARRAY_SIZE(malidp500_layers),
936 .layers = malidp500_layers,
938 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
939 MALIDP500_DE_IRQ_AXI_ERR |
940 MALIDP500_DE_IRQ_VSYNC |
941 MALIDP500_DE_IRQ_GLOBAL,
942 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
943 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
944 MALIDP500_DE_IRQ_AXI_ERR |
945 MALIDP500_DE_IRQ_SATURATION,
948 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
949 MALIDP500_SE_IRQ_CONF_VALID |
950 MALIDP500_SE_IRQ_GLOBAL,
951 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
952 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
953 MALIDP500_SE_IRQ_AXI_ERROR |
954 MALIDP500_SE_IRQ_OVERRUN,
957 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
958 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
960 .pixel_formats = malidp500_de_formats,
961 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
962 .bus_align_bytes = 8,
964 .query_hw = malidp500_query_hw,
965 .enter_config_mode = malidp500_enter_config_mode,
966 .leave_config_mode = malidp500_leave_config_mode,
967 .in_config_mode = malidp500_in_config_mode,
968 .set_config_valid = malidp500_set_config_valid,
969 .modeset = malidp500_modeset,
970 .rotmem_required = malidp500_rotmem_required,
971 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
972 .se_calc_mclk = malidp500_se_calc_mclk,
973 .enable_memwrite = malidp500_enable_memwrite,
974 .disable_memwrite = malidp500_disable_memwrite,
975 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
979 .coeffs_base = MALIDP550_COEFFS_BASE,
980 .se_base = MALIDP550_SE_BASE,
981 .dc_base = MALIDP550_DC_BASE,
982 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
983 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
984 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
985 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
986 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
987 .n_layers = ARRAY_SIZE(malidp550_layers),
988 .layers = malidp550_layers,
990 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
991 MALIDP550_DE_IRQ_VSYNC,
992 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
993 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
994 MALIDP550_DE_IRQ_SATURATION |
995 MALIDP550_DE_IRQ_AXI_ERR,
998 .irq_mask = MALIDP550_SE_IRQ_EOW,
999 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1000 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1001 MALIDP550_SE_IRQ_OVR |
1002 MALIDP550_SE_IRQ_IBSY,
1005 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1006 MALIDP550_DC_IRQ_SE,
1007 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1009 .pixel_formats = malidp550_de_formats,
1010 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1011 .bus_align_bytes = 8,
1013 .query_hw = malidp550_query_hw,
1014 .enter_config_mode = malidp550_enter_config_mode,
1015 .leave_config_mode = malidp550_leave_config_mode,
1016 .in_config_mode = malidp550_in_config_mode,
1017 .set_config_valid = malidp550_set_config_valid,
1018 .modeset = malidp550_modeset,
1019 .rotmem_required = malidp550_rotmem_required,
1020 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1021 .se_calc_mclk = malidp550_se_calc_mclk,
1022 .enable_memwrite = malidp550_enable_memwrite,
1023 .disable_memwrite = malidp550_disable_memwrite,
1028 .coeffs_base = MALIDP550_COEFFS_BASE,
1029 .se_base = MALIDP550_SE_BASE,
1030 .dc_base = MALIDP550_DC_BASE,
1031 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
1032 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
1033 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
1034 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
1035 .n_layers = ARRAY_SIZE(malidp650_layers),
1036 .layers = malidp650_layers,
1038 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1039 MALIDP650_DE_IRQ_DRIFT |
1040 MALIDP550_DE_IRQ_VSYNC,
1041 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1042 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1043 MALIDP650_DE_IRQ_DRIFT |
1044 MALIDP550_DE_IRQ_SATURATION |
1045 MALIDP550_DE_IRQ_AXI_ERR |
1046 MALIDP650_DE_IRQ_ACEV1 |
1047 MALIDP650_DE_IRQ_ACEV2 |
1048 MALIDP650_DE_IRQ_ACEG |
1049 MALIDP650_DE_IRQ_AXIEP,
1052 .irq_mask = MALIDP550_SE_IRQ_EOW,
1053 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1054 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1055 MALIDP550_SE_IRQ_OVR |
1056 MALIDP550_SE_IRQ_IBSY,
1059 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1060 MALIDP550_DC_IRQ_SE,
1061 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1063 .pixel_formats = malidp650_de_formats,
1064 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1065 .bus_align_bytes = 16,
1067 .query_hw = malidp650_query_hw,
1068 .enter_config_mode = malidp550_enter_config_mode,
1069 .leave_config_mode = malidp550_leave_config_mode,
1070 .in_config_mode = malidp550_in_config_mode,
1071 .set_config_valid = malidp550_set_config_valid,
1072 .modeset = malidp550_modeset,
1073 .rotmem_required = malidp650_rotmem_required,
1074 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1075 .se_calc_mclk = malidp550_se_calc_mclk,
1076 .enable_memwrite = malidp550_enable_memwrite,
1077 .disable_memwrite = malidp550_disable_memwrite,
1082 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
1083 u8 layer_id, u32 format, bool has_modifier)
1087 for (i = 0; i < map->n_pixel_formats; i++) {
1088 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
1089 (map->pixel_formats[i].format == format)) {
1091 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1092 * is supported by a different h/w format id than
1093 * DRM_FORMAT_YUYV (only).
1095 if (format == DRM_FORMAT_YUYV &&
1097 (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
1098 return AFBC_YUV_422_FORMAT_ID;
1100 return map->pixel_formats[i].id;
1104 return MALIDP_INVALID_FORMAT_ID;
1107 bool malidp_hw_format_is_linear_only(u32 format)
1110 case DRM_FORMAT_ARGB2101010:
1111 case DRM_FORMAT_RGBA1010102:
1112 case DRM_FORMAT_BGRA1010102:
1113 case DRM_FORMAT_ARGB8888:
1114 case DRM_FORMAT_RGBA8888:
1115 case DRM_FORMAT_BGRA8888:
1116 case DRM_FORMAT_XBGR8888:
1117 case DRM_FORMAT_XRGB8888:
1118 case DRM_FORMAT_RGBX8888:
1119 case DRM_FORMAT_BGRX8888:
1120 case DRM_FORMAT_RGB888:
1121 case DRM_FORMAT_RGB565:
1122 case DRM_FORMAT_ARGB1555:
1123 case DRM_FORMAT_RGBA5551:
1124 case DRM_FORMAT_BGRA5551:
1125 case DRM_FORMAT_UYVY:
1126 case DRM_FORMAT_XYUV8888:
1127 case DRM_FORMAT_XVYU2101010:
1128 case DRM_FORMAT_X0L2:
1129 case DRM_FORMAT_X0L0:
1136 bool malidp_hw_format_is_afbc_only(u32 format)
1139 case DRM_FORMAT_VUY888:
1140 case DRM_FORMAT_VUY101010:
1141 case DRM_FORMAT_YUV420_8BIT:
1142 case DRM_FORMAT_YUV420_10BIT:
1149 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1151 u32 base = malidp_get_block_base(hwdev, block);
1153 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1154 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1156 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1159 static irqreturn_t malidp_de_irq(int irq, void *arg)
1161 struct drm_device *drm = arg;
1162 struct malidp_drm *malidp = drm->dev_private;
1163 struct malidp_hw_device *hwdev;
1164 struct malidp_hw *hw;
1165 const struct malidp_irq_map *de;
1166 u32 status, mask, dc_status;
1167 irqreturn_t ret = IRQ_NONE;
1169 hwdev = malidp->dev;
1171 de = &hw->map.de_irq_map;
1174 * if we are suspended it is likely that we were invoked because
1175 * we share an interrupt line with some other driver, don't try
1176 * to read the hardware registers
1178 if (hwdev->pm_suspended)
1181 /* first handle the config valid IRQ */
1182 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1183 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1184 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1185 /* do we have a page flip event? */
1186 if (malidp->event != NULL) {
1187 spin_lock(&drm->event_lock);
1188 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1189 malidp->event = NULL;
1190 spin_unlock(&drm->event_lock);
1192 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1193 ret = IRQ_WAKE_THREAD;
1196 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1197 if (!(status & de->irq_mask))
1200 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1201 /* keep the status of the enabled interrupts, plus the error bits */
1202 status &= (mask | de->err_mask);
1203 if ((status & de->vsync_irq) && malidp->crtc.enabled)
1204 drm_crtc_handle_vblank(&malidp->crtc);
1206 #ifdef CONFIG_DEBUG_FS
1207 if (status & de->err_mask) {
1208 malidp_error(malidp, &malidp->de_errors, status,
1209 drm_crtc_vblank_count(&malidp->crtc));
1212 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1214 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1217 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1219 struct drm_device *drm = arg;
1220 struct malidp_drm *malidp = drm->dev_private;
1222 wake_up(&malidp->wq);
1227 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1229 /* ensure interrupts are disabled */
1230 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1231 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1232 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1233 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1235 /* first enable the DC block IRQs */
1236 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1237 hwdev->hw->map.dc_irq_map.irq_mask);
1239 /* now enable the DE block IRQs */
1240 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1241 hwdev->hw->map.de_irq_map.irq_mask);
1244 int malidp_de_irq_init(struct drm_device *drm, int irq)
1246 struct malidp_drm *malidp = drm->dev_private;
1247 struct malidp_hw_device *hwdev = malidp->dev;
1250 /* ensure interrupts are disabled */
1251 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1252 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1253 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1254 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1256 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1257 malidp_de_irq_thread_handler,
1258 IRQF_SHARED, "malidp-de", drm);
1260 DRM_ERROR("failed to install DE IRQ handler\n");
1264 malidp_de_irq_hw_init(hwdev);
1269 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1271 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1272 hwdev->hw->map.de_irq_map.irq_mask);
1273 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1274 hwdev->hw->map.dc_irq_map.irq_mask);
1277 static irqreturn_t malidp_se_irq(int irq, void *arg)
1279 struct drm_device *drm = arg;
1280 struct malidp_drm *malidp = drm->dev_private;
1281 struct malidp_hw_device *hwdev = malidp->dev;
1282 struct malidp_hw *hw = hwdev->hw;
1283 const struct malidp_irq_map *se = &hw->map.se_irq_map;
1287 * if we are suspended it is likely that we were invoked because
1288 * we share an interrupt line with some other driver, don't try
1289 * to read the hardware registers
1291 if (hwdev->pm_suspended)
1294 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1295 if (!(status & (se->irq_mask | se->err_mask)))
1298 #ifdef CONFIG_DEBUG_FS
1299 if (status & se->err_mask)
1300 malidp_error(malidp, &malidp->se_errors, status,
1301 drm_crtc_vblank_count(&malidp->crtc));
1303 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1306 if (status & se->vsync_irq) {
1307 switch (hwdev->mw_state) {
1309 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1312 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1313 /* disable writeback after stop */
1314 hwdev->mw_state = MW_NOT_ENABLED;
1317 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1318 /* fall through - to a new start */
1320 /* writeback started, need to emulate one-shot mode */
1321 hw->disable_memwrite(hwdev);
1323 * only set config_valid HW bit if there is no other update
1324 * in progress or if we raced ahead of the DE IRQ handler
1325 * and config_valid flag will not be update until later
1327 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1328 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1329 (status & hw->map.dc_irq_map.vsync_irq))
1330 hw->set_config_valid(hwdev, 1);
1335 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1340 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1342 /* ensure interrupts are disabled */
1343 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1344 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1346 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1347 hwdev->hw->map.se_irq_map.irq_mask);
1350 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1355 int malidp_se_irq_init(struct drm_device *drm, int irq)
1357 struct malidp_drm *malidp = drm->dev_private;
1358 struct malidp_hw_device *hwdev = malidp->dev;
1361 /* ensure interrupts are disabled */
1362 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1363 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1365 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1366 malidp_se_irq_thread_handler,
1367 IRQF_SHARED, "malidp-se", drm);
1369 DRM_ERROR("failed to install SE IRQ handler\n");
1373 hwdev->mw_state = MW_NOT_ENABLED;
1374 malidp_se_irq_hw_init(hwdev);
1379 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1381 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1382 hwdev->hw->map.se_irq_map.irq_mask);