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/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 * Program the RQoS register to avoid high resolutions flicker
385 * issue on the LS1028A.
387 if (hwdev->arqos_value) {
388 val = hwdev->arqos_value;
389 malidp_hw_setbits(hwdev, val, MALIDP500_RQOS_QUALITY);
393 int malidp_format_get_bpp(u32 fmt)
395 const struct drm_format_info *info = drm_format_info(fmt);
396 int bpp = info->cpp[0] * 8;
400 case DRM_FORMAT_VUY101010:
403 case DRM_FORMAT_YUV420_10BIT:
406 case DRM_FORMAT_YUV420_8BIT:
417 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
418 u16 h, u32 fmt, bool has_modifier)
421 * Each layer needs enough rotation memory to fit 8 lines
422 * worth of pixel data. Required size is then:
423 * size = rotated_width * (bpp / 8) * 8;
425 int bpp = malidp_format_get_bpp(fmt);
430 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
436 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
438 malidp_hw_write(hwdev,
439 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
440 scaling_control + MALIDP_SE_COEFFTAB_ADDR);
441 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
442 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
443 dp500_se_scaling_coeffs[coeffs_id][i]),
444 scaling_control + MALIDP_SE_COEFFTAB_DATA);
447 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
448 struct malidp_se_config *se_config,
449 struct malidp_se_config *old_config)
451 /* Get array indices into dp500_se_scaling_coeffs. */
452 u8 h = (u8)se_config->hcoeff - 1;
453 u8 v = (u8)se_config->vcoeff - 1;
455 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
456 v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
459 if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
460 se_config->vcoeff != old_config->vcoeff)) {
461 malidp500_se_write_pp_coefftab(hwdev,
462 (MALIDP_SE_V_COEFFTAB |
463 MALIDP_SE_H_COEFFTAB),
466 if (se_config->vcoeff != old_config->vcoeff)
467 malidp500_se_write_pp_coefftab(hwdev,
468 MALIDP_SE_V_COEFFTAB,
470 if (se_config->hcoeff != old_config->hcoeff)
471 malidp500_se_write_pp_coefftab(hwdev,
472 MALIDP_SE_H_COEFFTAB,
479 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
480 struct malidp_se_config *se_config,
481 struct videomode *vm)
484 unsigned long pxlclk = vm->pixelclock; /* Hz */
485 unsigned long htotal = vm->hactive + vm->hfront_porch +
486 vm->hback_porch + vm->hsync_len;
487 unsigned long input_size = se_config->input_w * se_config->input_h;
488 unsigned long a = 10;
492 * mclk = max(a, 1.5) * pxlclk
494 * To avoid float calculaiton, using 15 instead of 1.5 and div by
497 if (se_config->scale_enable) {
498 a = 15 * input_size / (htotal * se_config->output_h);
502 mclk = a * pxlclk / 10;
503 ret = clk_get_rate(hwdev->mclk);
505 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
512 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
513 dma_addr_t *addrs, s32 *pitches,
514 int num_planes, u16 w, u16 h, u32 fmt_id,
515 const s16 *rgb2yuv_coeffs)
517 u32 base = MALIDP500_SE_MEMWRITE_BASE;
518 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
520 /* enable the scaling engine block */
521 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
523 /* restart the writeback if already enabled */
524 if (hwdev->mw_state != MW_NOT_ENABLED)
525 hwdev->mw_state = MW_RESTART;
527 hwdev->mw_state = MW_START;
529 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
530 switch (num_planes) {
532 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
533 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
534 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
537 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
538 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
539 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
542 WARN(1, "Invalid number of planes");
545 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
546 MALIDP500_SE_MEMWRITE_OUT_SIZE);
548 if (rgb2yuv_coeffs) {
551 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
552 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
553 MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
557 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
562 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
564 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
566 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
567 hwdev->mw_state = MW_STOP;
568 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
569 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
572 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
574 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
575 u8 ln_size = (conf >> 4) & 0x3, rsize;
577 hwdev->min_line_size = 2;
581 hwdev->max_line_size = SZ_2K;
582 /* two banks of 64KB for rotation memory */
586 hwdev->max_line_size = SZ_4K;
587 /* two banks of 128KB for rotation memory */
591 hwdev->max_line_size = 1280;
592 /* two banks of 40KB for rotation memory */
597 hwdev->max_line_size = 0;
601 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
605 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
607 u32 status, count = 100;
609 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
611 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
612 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
615 * entering config mode can take as long as the rendering
616 * of a full frame, hence the long sleep here
618 usleep_range(1000, 10000);
621 WARN(count == 0, "timeout while entering config mode");
624 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
626 u32 status, count = 100;
628 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
629 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
631 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
632 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
634 usleep_range(100, 1000);
637 WARN(count == 0, "timeout while leaving config mode");
640 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
644 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
645 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
651 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
654 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
656 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
659 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
661 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
663 malidp_hw_write(hwdev, hwdev->output_color_depth,
664 hwdev->hw->map.out_depth_base);
665 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
667 * Mali-DP550 and Mali-DP650 encode the background color like this:
668 * - red @ MALIDP550_DE_BGND_COLOR[23:16]
669 * - green @ MALIDP550_DE_BGND_COLOR[15:8]
670 * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
672 * We need to truncate the least significant 4 bits from the default
673 * MALIDP_BGND_COLOR_x values
675 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
676 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
677 ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
678 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
680 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
681 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
682 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
684 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
685 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
686 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
688 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
689 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
690 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
691 val |= MALIDP550_HSYNCPOL;
692 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
693 val |= MALIDP550_VSYNCPOL;
694 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
696 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
697 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
699 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
700 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
702 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
705 static int malidpx50_get_bytes_per_column(u32 fmt)
707 u32 bytes_per_column;
710 /* 8 lines at 4 bytes per pixel */
711 case DRM_FORMAT_ARGB2101010:
712 case DRM_FORMAT_ABGR2101010:
713 case DRM_FORMAT_RGBA1010102:
714 case DRM_FORMAT_BGRA1010102:
715 case DRM_FORMAT_ARGB8888:
716 case DRM_FORMAT_ABGR8888:
717 case DRM_FORMAT_RGBA8888:
718 case DRM_FORMAT_BGRA8888:
719 case DRM_FORMAT_XRGB8888:
720 case DRM_FORMAT_XBGR8888:
721 case DRM_FORMAT_RGBX8888:
722 case DRM_FORMAT_BGRX8888:
723 case DRM_FORMAT_RGB888:
724 case DRM_FORMAT_BGR888:
725 /* 16 lines at 2 bytes per pixel */
726 case DRM_FORMAT_RGBA5551:
727 case DRM_FORMAT_ABGR1555:
728 case DRM_FORMAT_RGB565:
729 case DRM_FORMAT_BGR565:
730 case DRM_FORMAT_UYVY:
731 case DRM_FORMAT_YUYV:
732 case DRM_FORMAT_X0L0:
733 bytes_per_column = 32;
735 /* 16 lines at 1.5 bytes per pixel */
736 case DRM_FORMAT_NV12:
737 case DRM_FORMAT_YUV420:
738 /* 8 lines at 3 bytes per pixel */
739 case DRM_FORMAT_VUY888:
740 /* 16 lines at 12 bits per pixel */
741 case DRM_FORMAT_YUV420_8BIT:
742 /* 8 lines at 3 bytes per pixel */
743 case DRM_FORMAT_P010:
744 bytes_per_column = 24;
746 /* 8 lines at 30 bits per pixel */
747 case DRM_FORMAT_VUY101010:
748 /* 16 lines at 15 bits per pixel */
749 case DRM_FORMAT_YUV420_10BIT:
750 bytes_per_column = 30;
756 return bytes_per_column;
759 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
760 u16 h, u32 fmt, bool has_modifier)
762 int bytes_per_column = 0;
765 /* 8 lines at 15 bits per pixel */
766 case DRM_FORMAT_YUV420_10BIT:
767 bytes_per_column = 15;
769 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
770 case DRM_FORMAT_X0L2:
772 bytes_per_column = 8;
777 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
780 if (bytes_per_column == -EINVAL)
781 return bytes_per_column;
783 return w * bytes_per_column;
786 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
787 u16 h, u32 fmt, bool has_modifier)
789 int bytes_per_column = 0;
792 /* 16 lines at 2 bytes per pixel */
793 case DRM_FORMAT_X0L2:
794 bytes_per_column = 32;
797 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
800 if (bytes_per_column == -EINVAL)
801 return bytes_per_column;
803 return w * bytes_per_column;
806 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
807 struct malidp_se_config *se_config,
808 struct malidp_se_config *old_config)
810 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
811 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
812 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
813 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
815 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
816 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
820 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
821 struct malidp_se_config *se_config,
822 struct videomode *vm)
825 unsigned long pxlclk = vm->pixelclock;
826 unsigned long htotal = vm->hactive + vm->hfront_porch +
827 vm->hback_porch + vm->hsync_len;
828 unsigned long numerator = 1, denominator = 1;
831 if (se_config->scale_enable) {
832 numerator = max(se_config->input_w, se_config->output_w) *
834 numerator += se_config->output_w *
835 (se_config->output_h -
836 min(se_config->input_h, se_config->output_h));
837 denominator = (htotal - 2) * se_config->output_h;
840 /* mclk can't be slower than pxlclk. */
841 if (numerator < denominator)
842 numerator = denominator = 1;
843 mclk = (pxlclk * numerator) / denominator;
844 ret = clk_get_rate(hwdev->mclk);
846 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
853 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
854 dma_addr_t *addrs, s32 *pitches,
855 int num_planes, u16 w, u16 h, u32 fmt_id,
856 const s16 *rgb2yuv_coeffs)
858 u32 base = MALIDP550_SE_MEMWRITE_BASE;
859 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
861 /* enable the scaling engine block */
862 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
864 hwdev->mw_state = MW_ONESHOT;
866 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
867 switch (num_planes) {
869 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
870 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
871 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
874 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
875 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
876 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
879 WARN(1, "Invalid number of planes");
882 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
883 MALIDP550_SE_MEMWRITE_OUT_SIZE);
884 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
885 MALIDP550_SE_CONTROL);
887 if (rgb2yuv_coeffs) {
890 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
891 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
892 MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
899 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
901 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
903 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
904 MALIDP550_SE_CONTROL);
905 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
908 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
910 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
911 u8 ln_size = (conf >> 4) & 0x3, rsize;
913 hwdev->min_line_size = 4;
918 /* reserved values */
919 hwdev->max_line_size = 0;
922 hwdev->max_line_size = SZ_4K;
923 /* two banks of 128KB for rotation memory */
927 hwdev->max_line_size = 2560;
928 /* two banks of 80KB for rotation memory */
932 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
936 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
939 .coeffs_base = MALIDP500_COEFFS_BASE,
940 .se_base = MALIDP500_SE_BASE,
941 .dc_base = MALIDP500_DC_BASE,
942 .out_depth_base = MALIDP500_OUTPUT_DEPTH,
943 .features = 0, /* no CLEARIRQ register */
944 .n_layers = ARRAY_SIZE(malidp500_layers),
945 .layers = malidp500_layers,
947 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
948 MALIDP500_DE_IRQ_AXI_ERR |
949 MALIDP500_DE_IRQ_VSYNC |
950 MALIDP500_DE_IRQ_GLOBAL,
951 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
952 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
953 MALIDP500_DE_IRQ_AXI_ERR |
954 MALIDP500_DE_IRQ_SATURATION,
957 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
958 MALIDP500_SE_IRQ_CONF_VALID |
959 MALIDP500_SE_IRQ_GLOBAL,
960 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
961 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
962 MALIDP500_SE_IRQ_AXI_ERROR |
963 MALIDP500_SE_IRQ_OVERRUN,
966 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
967 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
969 .pixel_formats = malidp500_de_formats,
970 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
971 .bus_align_bytes = 8,
973 .query_hw = malidp500_query_hw,
974 .enter_config_mode = malidp500_enter_config_mode,
975 .leave_config_mode = malidp500_leave_config_mode,
976 .in_config_mode = malidp500_in_config_mode,
977 .set_config_valid = malidp500_set_config_valid,
978 .modeset = malidp500_modeset,
979 .rotmem_required = malidp500_rotmem_required,
980 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
981 .se_calc_mclk = malidp500_se_calc_mclk,
982 .enable_memwrite = malidp500_enable_memwrite,
983 .disable_memwrite = malidp500_disable_memwrite,
984 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
988 .coeffs_base = MALIDP550_COEFFS_BASE,
989 .se_base = MALIDP550_SE_BASE,
990 .dc_base = MALIDP550_DC_BASE,
991 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
992 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
993 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
994 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
995 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
996 .n_layers = ARRAY_SIZE(malidp550_layers),
997 .layers = malidp550_layers,
999 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1000 MALIDP550_DE_IRQ_VSYNC,
1001 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1002 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1003 MALIDP550_DE_IRQ_SATURATION |
1004 MALIDP550_DE_IRQ_AXI_ERR,
1007 .irq_mask = MALIDP550_SE_IRQ_EOW,
1008 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1009 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1010 MALIDP550_SE_IRQ_OVR |
1011 MALIDP550_SE_IRQ_IBSY,
1014 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1015 MALIDP550_DC_IRQ_SE,
1016 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1018 .pixel_formats = malidp550_de_formats,
1019 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1020 .bus_align_bytes = 8,
1022 .query_hw = malidp550_query_hw,
1023 .enter_config_mode = malidp550_enter_config_mode,
1024 .leave_config_mode = malidp550_leave_config_mode,
1025 .in_config_mode = malidp550_in_config_mode,
1026 .set_config_valid = malidp550_set_config_valid,
1027 .modeset = malidp550_modeset,
1028 .rotmem_required = malidp550_rotmem_required,
1029 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1030 .se_calc_mclk = malidp550_se_calc_mclk,
1031 .enable_memwrite = malidp550_enable_memwrite,
1032 .disable_memwrite = malidp550_disable_memwrite,
1037 .coeffs_base = MALIDP550_COEFFS_BASE,
1038 .se_base = MALIDP550_SE_BASE,
1039 .dc_base = MALIDP550_DC_BASE,
1040 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
1041 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
1042 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
1043 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
1044 .n_layers = ARRAY_SIZE(malidp650_layers),
1045 .layers = malidp650_layers,
1047 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1048 MALIDP650_DE_IRQ_DRIFT |
1049 MALIDP550_DE_IRQ_VSYNC,
1050 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1051 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1052 MALIDP650_DE_IRQ_DRIFT |
1053 MALIDP550_DE_IRQ_SATURATION |
1054 MALIDP550_DE_IRQ_AXI_ERR |
1055 MALIDP650_DE_IRQ_ACEV1 |
1056 MALIDP650_DE_IRQ_ACEV2 |
1057 MALIDP650_DE_IRQ_ACEG |
1058 MALIDP650_DE_IRQ_AXIEP,
1061 .irq_mask = MALIDP550_SE_IRQ_EOW,
1062 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1063 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1064 MALIDP550_SE_IRQ_OVR |
1065 MALIDP550_SE_IRQ_IBSY,
1068 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1069 MALIDP550_DC_IRQ_SE,
1070 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1072 .pixel_formats = malidp650_de_formats,
1073 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1074 .bus_align_bytes = 16,
1076 .query_hw = malidp650_query_hw,
1077 .enter_config_mode = malidp550_enter_config_mode,
1078 .leave_config_mode = malidp550_leave_config_mode,
1079 .in_config_mode = malidp550_in_config_mode,
1080 .set_config_valid = malidp550_set_config_valid,
1081 .modeset = malidp550_modeset,
1082 .rotmem_required = malidp650_rotmem_required,
1083 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1084 .se_calc_mclk = malidp550_se_calc_mclk,
1085 .enable_memwrite = malidp550_enable_memwrite,
1086 .disable_memwrite = malidp550_disable_memwrite,
1091 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
1092 u8 layer_id, u32 format, bool has_modifier)
1096 for (i = 0; i < map->n_pixel_formats; i++) {
1097 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
1098 (map->pixel_formats[i].format == format)) {
1100 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1101 * is supported by a different h/w format id than
1102 * DRM_FORMAT_YUYV (only).
1104 if (format == DRM_FORMAT_YUYV &&
1106 (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
1107 return AFBC_YUV_422_FORMAT_ID;
1109 return map->pixel_formats[i].id;
1113 return MALIDP_INVALID_FORMAT_ID;
1116 bool malidp_hw_format_is_linear_only(u32 format)
1119 case DRM_FORMAT_ARGB2101010:
1120 case DRM_FORMAT_RGBA1010102:
1121 case DRM_FORMAT_BGRA1010102:
1122 case DRM_FORMAT_ARGB8888:
1123 case DRM_FORMAT_RGBA8888:
1124 case DRM_FORMAT_BGRA8888:
1125 case DRM_FORMAT_XBGR8888:
1126 case DRM_FORMAT_XRGB8888:
1127 case DRM_FORMAT_RGBX8888:
1128 case DRM_FORMAT_BGRX8888:
1129 case DRM_FORMAT_RGB888:
1130 case DRM_FORMAT_RGB565:
1131 case DRM_FORMAT_ARGB1555:
1132 case DRM_FORMAT_RGBA5551:
1133 case DRM_FORMAT_BGRA5551:
1134 case DRM_FORMAT_UYVY:
1135 case DRM_FORMAT_XYUV8888:
1136 case DRM_FORMAT_XVYU2101010:
1137 case DRM_FORMAT_X0L2:
1138 case DRM_FORMAT_X0L0:
1145 bool malidp_hw_format_is_afbc_only(u32 format)
1148 case DRM_FORMAT_VUY888:
1149 case DRM_FORMAT_VUY101010:
1150 case DRM_FORMAT_YUV420_8BIT:
1151 case DRM_FORMAT_YUV420_10BIT:
1158 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1160 u32 base = malidp_get_block_base(hwdev, block);
1162 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1163 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1165 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1168 static irqreturn_t malidp_de_irq(int irq, void *arg)
1170 struct drm_device *drm = arg;
1171 struct malidp_drm *malidp = drm->dev_private;
1172 struct malidp_hw_device *hwdev;
1173 struct malidp_hw *hw;
1174 const struct malidp_irq_map *de;
1175 u32 status, mask, dc_status;
1176 irqreturn_t ret = IRQ_NONE;
1178 hwdev = malidp->dev;
1180 de = &hw->map.de_irq_map;
1183 * if we are suspended it is likely that we were invoked because
1184 * we share an interrupt line with some other driver, don't try
1185 * to read the hardware registers
1187 if (hwdev->pm_suspended)
1190 /* first handle the config valid IRQ */
1191 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1192 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1193 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1194 /* do we have a page flip event? */
1195 if (malidp->event != NULL) {
1196 spin_lock(&drm->event_lock);
1197 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1198 malidp->event = NULL;
1199 spin_unlock(&drm->event_lock);
1201 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1202 ret = IRQ_WAKE_THREAD;
1205 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1206 if (!(status & de->irq_mask))
1209 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1210 /* keep the status of the enabled interrupts, plus the error bits */
1211 status &= (mask | de->err_mask);
1212 if ((status & de->vsync_irq) && malidp->crtc.enabled)
1213 drm_crtc_handle_vblank(&malidp->crtc);
1215 #ifdef CONFIG_DEBUG_FS
1216 if (status & de->err_mask) {
1217 malidp_error(malidp, &malidp->de_errors, status,
1218 drm_crtc_vblank_count(&malidp->crtc));
1221 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1223 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1226 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1228 struct drm_device *drm = arg;
1229 struct malidp_drm *malidp = drm->dev_private;
1231 wake_up(&malidp->wq);
1236 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1238 /* ensure interrupts are disabled */
1239 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1240 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1241 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1242 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1244 /* first enable the DC block IRQs */
1245 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1246 hwdev->hw->map.dc_irq_map.irq_mask);
1248 /* now enable the DE block IRQs */
1249 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1250 hwdev->hw->map.de_irq_map.irq_mask);
1253 int malidp_de_irq_init(struct drm_device *drm, int irq)
1255 struct malidp_drm *malidp = drm->dev_private;
1256 struct malidp_hw_device *hwdev = malidp->dev;
1259 /* ensure interrupts are disabled */
1260 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1261 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1262 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1263 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1265 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1266 malidp_de_irq_thread_handler,
1267 IRQF_SHARED, "malidp-de", drm);
1269 DRM_ERROR("failed to install DE IRQ handler\n");
1273 malidp_de_irq_hw_init(hwdev);
1278 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1280 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1281 hwdev->hw->map.de_irq_map.irq_mask);
1282 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1283 hwdev->hw->map.dc_irq_map.irq_mask);
1286 static irqreturn_t malidp_se_irq(int irq, void *arg)
1288 struct drm_device *drm = arg;
1289 struct malidp_drm *malidp = drm->dev_private;
1290 struct malidp_hw_device *hwdev = malidp->dev;
1291 struct malidp_hw *hw = hwdev->hw;
1292 const struct malidp_irq_map *se = &hw->map.se_irq_map;
1296 * if we are suspended it is likely that we were invoked because
1297 * we share an interrupt line with some other driver, don't try
1298 * to read the hardware registers
1300 if (hwdev->pm_suspended)
1303 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1304 if (!(status & (se->irq_mask | se->err_mask)))
1307 #ifdef CONFIG_DEBUG_FS
1308 if (status & se->err_mask)
1309 malidp_error(malidp, &malidp->se_errors, status,
1310 drm_crtc_vblank_count(&malidp->crtc));
1312 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1315 if (status & se->vsync_irq) {
1316 switch (hwdev->mw_state) {
1318 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1321 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1322 /* disable writeback after stop */
1323 hwdev->mw_state = MW_NOT_ENABLED;
1326 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1327 fallthrough; /* to a new start */
1329 /* writeback started, need to emulate one-shot mode */
1330 hw->disable_memwrite(hwdev);
1332 * only set config_valid HW bit if there is no other update
1333 * in progress or if we raced ahead of the DE IRQ handler
1334 * and config_valid flag will not be update until later
1336 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1337 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1338 (status & hw->map.dc_irq_map.vsync_irq))
1339 hw->set_config_valid(hwdev, 1);
1344 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1349 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1351 /* ensure interrupts are disabled */
1352 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1353 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1355 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1356 hwdev->hw->map.se_irq_map.irq_mask);
1359 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1364 int malidp_se_irq_init(struct drm_device *drm, int irq)
1366 struct malidp_drm *malidp = drm->dev_private;
1367 struct malidp_hw_device *hwdev = malidp->dev;
1370 /* ensure interrupts are disabled */
1371 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1372 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1374 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1375 malidp_se_irq_thread_handler,
1376 IRQF_SHARED, "malidp-se", drm);
1378 DRM_ERROR("failed to install SE IRQ handler\n");
1382 hwdev->mw_state = MW_NOT_ENABLED;
1383 malidp_se_irq_hw_init(hwdev);
1388 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1390 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1391 hwdev->hw->map.se_irq_map.irq_mask);