2 * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
5 * This program is free software and is provided to you under the terms of the
6 * GNU General Public License version 2 as published by the Free Software
7 * Foundation, and any use by you of this program is subject to the terms
10 * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
11 * the difference between various versions of the hardware is being dealt with
12 * in an attempt to provide to the rest of the driver code a unified view
15 #include <linux/clk.h>
16 #include <linux/types.h>
19 #include <video/videomode.h>
20 #include <video/display_timing.h>
22 #include "malidp_drv.h"
23 #include "malidp_hw.h"
24 #include "malidp_mw.h"
27 MW_NOT_ENABLED = 0, /* SE writeback not enabled */
28 MW_ONESHOT, /* SE in one-shot mode for writeback */
29 MW_START, /* SE started writeback */
30 MW_RESTART, /* SE will start another writeback after this one */
31 MW_STOP, /* SE needs to stop after this writeback */
34 static const struct malidp_format_id malidp500_de_formats[] = {
35 /* fourcc, layers supporting the format, internal id */
36 { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 0 },
37 { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 1 },
38 { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 2 },
39 { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 3 },
40 { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 4 },
41 { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE, 5 },
42 { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 6 },
43 { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 7 },
44 { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 8 },
45 { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 9 },
46 { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
47 { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
48 { DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
49 { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
50 { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
51 { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
52 { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
53 /* These are supported with AFBC only */
54 { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
55 { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
56 { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
57 { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
60 #define MALIDP_ID(__group, __format) \
61 ((((__group) & 0x7) << 3) | ((__format) & 0x7))
63 #define AFBC_YUV_422_FORMAT_ID MALIDP_ID(5, 1)
65 #define MALIDP_COMMON_FORMATS \
66 /* fourcc, layers supporting the format, internal id */ \
67 { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
68 { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
69 { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
70 { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
71 { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
72 { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
73 { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
74 { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
75 { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
76 { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
77 { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
78 { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
79 { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
80 { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
81 { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
82 { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
83 { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
84 { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
85 /* This is only supported with linear modifier */ \
86 { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
87 /* This is only supported with AFBC modifier */ \
88 { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
89 { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
90 /* This is only supported with linear modifier */ \
91 { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
92 { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
93 /* This is only supported with AFBC modifier */ \
94 { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
95 { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
96 /* This is only supported with linear modifier */ \
97 { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
98 /* This is only supported with AFBC modifier */ \
99 { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
100 { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
101 /* This is only supported with AFBC modifier */ \
102 { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
103 { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
105 static const struct malidp_format_id malidp550_de_formats[] = {
106 MALIDP_COMMON_FORMATS,
109 static const struct malidp_format_id malidp650_de_formats[] = {
110 MALIDP_COMMON_FORMATS,
111 { DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)},
114 static const struct malidp_layer malidp500_layers[] = {
115 /* id, base address, fb pointer address base, stride offset,
116 * yuv2rgb matrix offset, mmu control register offset, rotation_features
118 { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
119 MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
120 MALIDP500_DE_LV_AD_CTRL },
121 { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
122 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
123 MALIDP500_DE_LG1_AD_CTRL },
124 { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
125 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
126 MALIDP500_DE_LG2_AD_CTRL },
129 static const struct malidp_layer malidp550_layers[] = {
130 /* id, base address, fb pointer address base, stride offset,
131 * yuv2rgb matrix offset, mmu control register offset, rotation_features
133 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
134 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
135 MALIDP550_DE_LV1_AD_CTRL },
136 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
137 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
138 MALIDP550_DE_LG_AD_CTRL },
139 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
140 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
141 MALIDP550_DE_LV2_AD_CTRL },
142 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
143 MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
146 static const struct malidp_layer malidp650_layers[] = {
147 /* id, base address, fb pointer address base, stride offset,
148 * yuv2rgb matrix offset, mmu control register offset,
151 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
152 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
153 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
154 MALIDP550_DE_LV1_AD_CTRL },
155 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
156 MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
157 ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
158 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
159 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
160 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
161 MALIDP550_DE_LV2_AD_CTRL },
162 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
163 MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
167 const u64 malidp_format_modifiers[] = {
168 /* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
169 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
170 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
172 /* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
173 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
175 /* All 8 or 10 bit YUV 444 formats. */
176 /* In DP550, 10 bit YUV 420 format also supported */
177 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
179 /* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
180 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
181 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
183 /* YUV 420, 422 P1 8, 10 bit formats */
184 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
185 DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
188 DRM_FORMAT_MOD_LINEAR,
190 DRM_FORMAT_MOD_INVALID
193 #define SE_N_SCALING_COEFFS 96
194 static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
195 [MALIDP_UPSCALING_COEFFS - 1] = {
196 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
197 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
198 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
199 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
200 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
201 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
202 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
203 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
204 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
205 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
206 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
207 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
209 [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
210 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
211 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
212 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
213 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
214 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
215 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
216 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
217 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
218 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
219 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
220 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
221 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
223 [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
224 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
225 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
226 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
227 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
228 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
229 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
230 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
231 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
232 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
233 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
234 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
235 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
237 [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
238 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
239 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
240 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
241 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
242 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
243 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
244 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
245 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
246 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
247 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
248 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
249 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
251 [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
252 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
253 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
254 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
255 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
256 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
257 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
258 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
259 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
260 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
261 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
262 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
263 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
267 #define MALIDP_DE_DEFAULT_PREFETCH_START 5
269 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
271 u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
272 /* bit 4 of the CONFIG_ID register holds the line size multiplier */
273 u8 ln_size_mult = conf & 0x10 ? 2 : 1;
275 hwdev->min_line_size = 2;
276 hwdev->max_line_size = SZ_2K * ln_size_mult;
277 hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
278 hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
283 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
285 u32 status, count = 100;
287 malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
289 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
290 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
293 * entering config mode can take as long as the rendering
294 * of a full frame, hence the long sleep here
296 usleep_range(1000, 10000);
299 WARN(count == 0, "timeout while entering config mode");
302 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
304 u32 status, count = 100;
306 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
307 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
309 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
310 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
312 usleep_range(100, 1000);
315 WARN(count == 0, "timeout while leaving config mode");
318 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
322 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
323 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
329 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
332 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
334 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
337 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
341 malidp_hw_write(hwdev, hwdev->output_color_depth,
342 hwdev->hw->map.out_depth_base);
343 malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
344 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
345 val |= MALIDP500_HSYNCPOL;
346 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
347 val |= MALIDP500_VSYNCPOL;
348 val |= MALIDP_DE_DEFAULT_PREFETCH_START;
349 malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
352 * Mali-DP500 encodes the background color like this:
353 * - red @ MALIDP500_BGND_COLOR[12:0]
354 * - green @ MALIDP500_BGND_COLOR[27:16]
355 * - blue @ (MALIDP500_BGND_COLOR + 4)[12:0]
357 val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
358 (MALIDP_BGND_COLOR_R & 0xfff);
359 malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
360 malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
362 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
363 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
364 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
366 val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
367 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
368 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
370 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
371 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
372 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
374 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
375 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
377 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
378 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
380 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
383 int malidp_format_get_bpp(u32 fmt)
385 int bpp = drm_format_plane_cpp(fmt, 0) * 8;
389 case DRM_FORMAT_VUY101010:
391 case DRM_FORMAT_YUV420_10BIT:
394 case DRM_FORMAT_YUV420_8BIT:
405 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
406 u16 h, u32 fmt, bool has_modifier)
409 * Each layer needs enough rotation memory to fit 8 lines
410 * worth of pixel data. Required size is then:
411 * size = rotated_width * (bpp / 8) * 8;
413 int bpp = malidp_format_get_bpp(fmt);
418 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
424 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
426 malidp_hw_write(hwdev,
427 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
428 scaling_control + MALIDP_SE_COEFFTAB_ADDR);
429 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
430 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
431 dp500_se_scaling_coeffs[coeffs_id][i]),
432 scaling_control + MALIDP_SE_COEFFTAB_DATA);
435 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
436 struct malidp_se_config *se_config,
437 struct malidp_se_config *old_config)
439 /* Get array indices into dp500_se_scaling_coeffs. */
440 u8 h = (u8)se_config->hcoeff - 1;
441 u8 v = (u8)se_config->vcoeff - 1;
443 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
444 v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
447 if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
448 se_config->vcoeff != old_config->vcoeff)) {
449 malidp500_se_write_pp_coefftab(hwdev,
450 (MALIDP_SE_V_COEFFTAB |
451 MALIDP_SE_H_COEFFTAB),
454 if (se_config->vcoeff != old_config->vcoeff)
455 malidp500_se_write_pp_coefftab(hwdev,
456 MALIDP_SE_V_COEFFTAB,
458 if (se_config->hcoeff != old_config->hcoeff)
459 malidp500_se_write_pp_coefftab(hwdev,
460 MALIDP_SE_H_COEFFTAB,
467 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
468 struct malidp_se_config *se_config,
469 struct videomode *vm)
472 unsigned long pxlclk = vm->pixelclock; /* Hz */
473 unsigned long htotal = vm->hactive + vm->hfront_porch +
474 vm->hback_porch + vm->hsync_len;
475 unsigned long input_size = se_config->input_w * se_config->input_h;
476 unsigned long a = 10;
480 * mclk = max(a, 1.5) * pxlclk
482 * To avoid float calculaiton, using 15 instead of 1.5 and div by
485 if (se_config->scale_enable) {
486 a = 15 * input_size / (htotal * se_config->output_h);
490 mclk = a * pxlclk / 10;
491 ret = clk_get_rate(hwdev->mclk);
493 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
500 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
501 dma_addr_t *addrs, s32 *pitches,
502 int num_planes, u16 w, u16 h, u32 fmt_id,
503 const s16 *rgb2yuv_coeffs)
505 u32 base = MALIDP500_SE_MEMWRITE_BASE;
506 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
508 /* enable the scaling engine block */
509 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
511 /* restart the writeback if already enabled */
512 if (hwdev->mw_state != MW_NOT_ENABLED)
513 hwdev->mw_state = MW_RESTART;
515 hwdev->mw_state = MW_START;
517 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
518 switch (num_planes) {
520 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
521 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
522 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
525 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
526 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
527 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
530 WARN(1, "Invalid number of planes");
533 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
534 MALIDP500_SE_MEMWRITE_OUT_SIZE);
536 if (rgb2yuv_coeffs) {
539 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
540 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
541 MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
545 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
550 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
552 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
554 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
555 hwdev->mw_state = MW_STOP;
556 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
557 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
560 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
562 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
563 u8 ln_size = (conf >> 4) & 0x3, rsize;
565 hwdev->min_line_size = 2;
569 hwdev->max_line_size = SZ_2K;
570 /* two banks of 64KB for rotation memory */
574 hwdev->max_line_size = SZ_4K;
575 /* two banks of 128KB for rotation memory */
579 hwdev->max_line_size = 1280;
580 /* two banks of 40KB for rotation memory */
585 hwdev->max_line_size = 0;
589 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
593 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
595 u32 status, count = 100;
597 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
599 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
600 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
603 * entering config mode can take as long as the rendering
604 * of a full frame, hence the long sleep here
606 usleep_range(1000, 10000);
609 WARN(count == 0, "timeout while entering config mode");
612 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
614 u32 status, count = 100;
616 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
617 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
619 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
620 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
622 usleep_range(100, 1000);
625 WARN(count == 0, "timeout while leaving config mode");
628 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
632 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
633 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
639 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
642 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
644 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
647 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
649 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
651 malidp_hw_write(hwdev, hwdev->output_color_depth,
652 hwdev->hw->map.out_depth_base);
653 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
655 * Mali-DP550 and Mali-DP650 encode the background color like this:
656 * - red @ MALIDP550_DE_BGND_COLOR[23:16]
657 * - green @ MALIDP550_DE_BGND_COLOR[15:8]
658 * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
660 * We need to truncate the least significant 4 bits from the default
661 * MALIDP_BGND_COLOR_x values
663 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
664 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
665 ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
666 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
668 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
669 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
670 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
672 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
673 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
674 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
676 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
677 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
678 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
679 val |= MALIDP550_HSYNCPOL;
680 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
681 val |= MALIDP550_VSYNCPOL;
682 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
684 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
685 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
687 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
688 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
690 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
693 static int malidpx50_get_bytes_per_column(u32 fmt)
695 u32 bytes_per_column;
698 /* 8 lines at 4 bytes per pixel */
699 case DRM_FORMAT_ARGB2101010:
700 case DRM_FORMAT_ABGR2101010:
701 case DRM_FORMAT_RGBA1010102:
702 case DRM_FORMAT_BGRA1010102:
703 case DRM_FORMAT_ARGB8888:
704 case DRM_FORMAT_ABGR8888:
705 case DRM_FORMAT_RGBA8888:
706 case DRM_FORMAT_BGRA8888:
707 case DRM_FORMAT_XRGB8888:
708 case DRM_FORMAT_XBGR8888:
709 case DRM_FORMAT_RGBX8888:
710 case DRM_FORMAT_BGRX8888:
711 case DRM_FORMAT_RGB888:
712 case DRM_FORMAT_BGR888:
713 /* 16 lines at 2 bytes per pixel */
714 case DRM_FORMAT_RGBA5551:
715 case DRM_FORMAT_ABGR1555:
716 case DRM_FORMAT_RGB565:
717 case DRM_FORMAT_BGR565:
718 case DRM_FORMAT_UYVY:
719 case DRM_FORMAT_YUYV:
720 case DRM_FORMAT_X0L0:
721 bytes_per_column = 32;
723 /* 16 lines at 1.5 bytes per pixel */
724 case DRM_FORMAT_NV12:
725 case DRM_FORMAT_YUV420:
726 /* 8 lines at 3 bytes per pixel */
727 case DRM_FORMAT_VUY888:
728 /* 16 lines at 12 bits per pixel */
729 case DRM_FORMAT_YUV420_8BIT:
730 /* 8 lines at 3 bytes per pixel */
731 case DRM_FORMAT_P010:
732 bytes_per_column = 24;
734 /* 8 lines at 30 bits per pixel */
735 case DRM_FORMAT_VUY101010:
736 /* 16 lines at 15 bits per pixel */
737 case DRM_FORMAT_YUV420_10BIT:
738 bytes_per_column = 30;
744 return bytes_per_column;
747 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
748 u16 h, u32 fmt, bool has_modifier)
750 int bytes_per_column = 0;
753 /* 8 lines at 15 bits per pixel */
754 case DRM_FORMAT_YUV420_10BIT:
755 bytes_per_column = 15;
757 /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
758 case DRM_FORMAT_X0L2:
760 bytes_per_column = 8;
765 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
768 if (bytes_per_column == -EINVAL)
769 return bytes_per_column;
771 return w * bytes_per_column;
774 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
775 u16 h, u32 fmt, bool has_modifier)
777 int bytes_per_column = 0;
780 /* 16 lines at 2 bytes per pixel */
781 case DRM_FORMAT_X0L2:
782 bytes_per_column = 32;
785 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
788 if (bytes_per_column == -EINVAL)
789 return bytes_per_column;
791 return w * bytes_per_column;
794 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
795 struct malidp_se_config *se_config,
796 struct malidp_se_config *old_config)
798 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
799 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
800 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
801 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
803 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
804 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
808 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
809 struct malidp_se_config *se_config,
810 struct videomode *vm)
813 unsigned long pxlclk = vm->pixelclock;
814 unsigned long htotal = vm->hactive + vm->hfront_porch +
815 vm->hback_porch + vm->hsync_len;
816 unsigned long numerator = 1, denominator = 1;
819 if (se_config->scale_enable) {
820 numerator = max(se_config->input_w, se_config->output_w) *
822 numerator += se_config->output_w *
823 (se_config->output_h -
824 min(se_config->input_h, se_config->output_h));
825 denominator = (htotal - 2) * se_config->output_h;
828 /* mclk can't be slower than pxlclk. */
829 if (numerator < denominator)
830 numerator = denominator = 1;
831 mclk = (pxlclk * numerator) / denominator;
832 ret = clk_get_rate(hwdev->mclk);
834 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
841 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
842 dma_addr_t *addrs, s32 *pitches,
843 int num_planes, u16 w, u16 h, u32 fmt_id,
844 const s16 *rgb2yuv_coeffs)
846 u32 base = MALIDP550_SE_MEMWRITE_BASE;
847 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
849 /* enable the scaling engine block */
850 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
852 hwdev->mw_state = MW_ONESHOT;
854 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
855 switch (num_planes) {
857 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
858 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
859 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
862 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
863 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
864 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
867 WARN(1, "Invalid number of planes");
870 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
871 MALIDP550_SE_MEMWRITE_OUT_SIZE);
872 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
873 MALIDP550_SE_CONTROL);
875 if (rgb2yuv_coeffs) {
878 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
879 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
880 MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
887 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
889 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
891 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
892 MALIDP550_SE_CONTROL);
893 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
896 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
898 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
899 u8 ln_size = (conf >> 4) & 0x3, rsize;
901 hwdev->min_line_size = 4;
906 /* reserved values */
907 hwdev->max_line_size = 0;
910 hwdev->max_line_size = SZ_4K;
911 /* two banks of 128KB for rotation memory */
915 hwdev->max_line_size = 2560;
916 /* two banks of 80KB for rotation memory */
920 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
924 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
927 .coeffs_base = MALIDP500_COEFFS_BASE,
928 .se_base = MALIDP500_SE_BASE,
929 .dc_base = MALIDP500_DC_BASE,
930 .out_depth_base = MALIDP500_OUTPUT_DEPTH,
931 .features = 0, /* no CLEARIRQ register */
932 .n_layers = ARRAY_SIZE(malidp500_layers),
933 .layers = malidp500_layers,
935 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
936 MALIDP500_DE_IRQ_AXI_ERR |
937 MALIDP500_DE_IRQ_VSYNC |
938 MALIDP500_DE_IRQ_GLOBAL,
939 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
940 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
941 MALIDP500_DE_IRQ_AXI_ERR |
942 MALIDP500_DE_IRQ_SATURATION,
945 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
946 MALIDP500_SE_IRQ_CONF_VALID |
947 MALIDP500_SE_IRQ_GLOBAL,
948 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
949 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
950 MALIDP500_SE_IRQ_AXI_ERROR |
951 MALIDP500_SE_IRQ_OVERRUN,
954 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
955 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
957 .pixel_formats = malidp500_de_formats,
958 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
959 .bus_align_bytes = 8,
961 .query_hw = malidp500_query_hw,
962 .enter_config_mode = malidp500_enter_config_mode,
963 .leave_config_mode = malidp500_leave_config_mode,
964 .in_config_mode = malidp500_in_config_mode,
965 .set_config_valid = malidp500_set_config_valid,
966 .modeset = malidp500_modeset,
967 .rotmem_required = malidp500_rotmem_required,
968 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
969 .se_calc_mclk = malidp500_se_calc_mclk,
970 .enable_memwrite = malidp500_enable_memwrite,
971 .disable_memwrite = malidp500_disable_memwrite,
972 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
976 .coeffs_base = MALIDP550_COEFFS_BASE,
977 .se_base = MALIDP550_SE_BASE,
978 .dc_base = MALIDP550_DC_BASE,
979 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
980 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
981 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
982 MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
983 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
984 .n_layers = ARRAY_SIZE(malidp550_layers),
985 .layers = malidp550_layers,
987 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
988 MALIDP550_DE_IRQ_VSYNC,
989 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
990 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
991 MALIDP550_DE_IRQ_SATURATION |
992 MALIDP550_DE_IRQ_AXI_ERR,
995 .irq_mask = MALIDP550_SE_IRQ_EOW,
996 .vsync_irq = MALIDP550_SE_IRQ_EOW,
997 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
998 MALIDP550_SE_IRQ_OVR |
999 MALIDP550_SE_IRQ_IBSY,
1002 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1003 MALIDP550_DC_IRQ_SE,
1004 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1006 .pixel_formats = malidp550_de_formats,
1007 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1008 .bus_align_bytes = 8,
1010 .query_hw = malidp550_query_hw,
1011 .enter_config_mode = malidp550_enter_config_mode,
1012 .leave_config_mode = malidp550_leave_config_mode,
1013 .in_config_mode = malidp550_in_config_mode,
1014 .set_config_valid = malidp550_set_config_valid,
1015 .modeset = malidp550_modeset,
1016 .rotmem_required = malidp550_rotmem_required,
1017 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1018 .se_calc_mclk = malidp550_se_calc_mclk,
1019 .enable_memwrite = malidp550_enable_memwrite,
1020 .disable_memwrite = malidp550_disable_memwrite,
1025 .coeffs_base = MALIDP550_COEFFS_BASE,
1026 .se_base = MALIDP550_SE_BASE,
1027 .dc_base = MALIDP550_DC_BASE,
1028 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
1029 .features = MALIDP_REGMAP_HAS_CLEARIRQ |
1030 MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
1031 MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
1032 .n_layers = ARRAY_SIZE(malidp650_layers),
1033 .layers = malidp650_layers,
1035 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1036 MALIDP650_DE_IRQ_DRIFT |
1037 MALIDP550_DE_IRQ_VSYNC,
1038 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1039 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1040 MALIDP650_DE_IRQ_DRIFT |
1041 MALIDP550_DE_IRQ_SATURATION |
1042 MALIDP550_DE_IRQ_AXI_ERR |
1043 MALIDP650_DE_IRQ_ACEV1 |
1044 MALIDP650_DE_IRQ_ACEV2 |
1045 MALIDP650_DE_IRQ_ACEG |
1046 MALIDP650_DE_IRQ_AXIEP,
1049 .irq_mask = MALIDP550_SE_IRQ_EOW,
1050 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1051 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1052 MALIDP550_SE_IRQ_OVR |
1053 MALIDP550_SE_IRQ_IBSY,
1056 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1057 MALIDP550_DC_IRQ_SE,
1058 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1060 .pixel_formats = malidp650_de_formats,
1061 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1062 .bus_align_bytes = 16,
1064 .query_hw = malidp650_query_hw,
1065 .enter_config_mode = malidp550_enter_config_mode,
1066 .leave_config_mode = malidp550_leave_config_mode,
1067 .in_config_mode = malidp550_in_config_mode,
1068 .set_config_valid = malidp550_set_config_valid,
1069 .modeset = malidp550_modeset,
1070 .rotmem_required = malidp650_rotmem_required,
1071 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1072 .se_calc_mclk = malidp550_se_calc_mclk,
1073 .enable_memwrite = malidp550_enable_memwrite,
1074 .disable_memwrite = malidp550_disable_memwrite,
1079 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
1080 u8 layer_id, u32 format, bool has_modifier)
1084 for (i = 0; i < map->n_pixel_formats; i++) {
1085 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
1086 (map->pixel_formats[i].format == format)) {
1088 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1089 * is supported by a different h/w format id than
1090 * DRM_FORMAT_YUYV (only).
1092 if (format == DRM_FORMAT_YUYV &&
1094 (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
1095 return AFBC_YUV_422_FORMAT_ID;
1097 return map->pixel_formats[i].id;
1101 return MALIDP_INVALID_FORMAT_ID;
1104 bool malidp_hw_format_is_linear_only(u32 format)
1107 case DRM_FORMAT_ARGB2101010:
1108 case DRM_FORMAT_RGBA1010102:
1109 case DRM_FORMAT_BGRA1010102:
1110 case DRM_FORMAT_ARGB8888:
1111 case DRM_FORMAT_RGBA8888:
1112 case DRM_FORMAT_BGRA8888:
1113 case DRM_FORMAT_XBGR8888:
1114 case DRM_FORMAT_XRGB8888:
1115 case DRM_FORMAT_RGBX8888:
1116 case DRM_FORMAT_BGRX8888:
1117 case DRM_FORMAT_RGB888:
1118 case DRM_FORMAT_RGB565:
1119 case DRM_FORMAT_ARGB1555:
1120 case DRM_FORMAT_RGBA5551:
1121 case DRM_FORMAT_BGRA5551:
1122 case DRM_FORMAT_UYVY:
1123 case DRM_FORMAT_XYUV8888:
1124 case DRM_FORMAT_XVYU2101010:
1125 case DRM_FORMAT_X0L2:
1126 case DRM_FORMAT_X0L0:
1133 bool malidp_hw_format_is_afbc_only(u32 format)
1136 case DRM_FORMAT_VUY888:
1137 case DRM_FORMAT_VUY101010:
1138 case DRM_FORMAT_YUV420_8BIT:
1139 case DRM_FORMAT_YUV420_10BIT:
1146 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1148 u32 base = malidp_get_block_base(hwdev, block);
1150 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1151 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1153 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1156 static irqreturn_t malidp_de_irq(int irq, void *arg)
1158 struct drm_device *drm = arg;
1159 struct malidp_drm *malidp = drm->dev_private;
1160 struct malidp_hw_device *hwdev;
1161 struct malidp_hw *hw;
1162 const struct malidp_irq_map *de;
1163 u32 status, mask, dc_status;
1164 irqreturn_t ret = IRQ_NONE;
1166 hwdev = malidp->dev;
1168 de = &hw->map.de_irq_map;
1171 * if we are suspended it is likely that we were invoked because
1172 * we share an interrupt line with some other driver, don't try
1173 * to read the hardware registers
1175 if (hwdev->pm_suspended)
1178 /* first handle the config valid IRQ */
1179 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1180 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1181 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1182 /* do we have a page flip event? */
1183 if (malidp->event != NULL) {
1184 spin_lock(&drm->event_lock);
1185 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1186 malidp->event = NULL;
1187 spin_unlock(&drm->event_lock);
1189 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1190 ret = IRQ_WAKE_THREAD;
1193 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1194 if (!(status & de->irq_mask))
1197 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1198 /* keep the status of the enabled interrupts, plus the error bits */
1199 status &= (mask | de->err_mask);
1200 if ((status & de->vsync_irq) && malidp->crtc.enabled)
1201 drm_crtc_handle_vblank(&malidp->crtc);
1203 #ifdef CONFIG_DEBUG_FS
1204 if (status & de->err_mask) {
1205 malidp_error(malidp, &malidp->de_errors, status,
1206 drm_crtc_vblank_count(&malidp->crtc));
1209 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1211 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1214 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1216 struct drm_device *drm = arg;
1217 struct malidp_drm *malidp = drm->dev_private;
1219 wake_up(&malidp->wq);
1224 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1226 /* ensure interrupts are disabled */
1227 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1228 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1229 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1230 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1232 /* first enable the DC block IRQs */
1233 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1234 hwdev->hw->map.dc_irq_map.irq_mask);
1236 /* now enable the DE block IRQs */
1237 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1238 hwdev->hw->map.de_irq_map.irq_mask);
1241 int malidp_de_irq_init(struct drm_device *drm, int irq)
1243 struct malidp_drm *malidp = drm->dev_private;
1244 struct malidp_hw_device *hwdev = malidp->dev;
1247 /* ensure interrupts are disabled */
1248 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1249 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1250 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1251 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1253 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1254 malidp_de_irq_thread_handler,
1255 IRQF_SHARED, "malidp-de", drm);
1257 DRM_ERROR("failed to install DE IRQ handler\n");
1261 malidp_de_irq_hw_init(hwdev);
1266 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1268 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1269 hwdev->hw->map.de_irq_map.irq_mask);
1270 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1271 hwdev->hw->map.dc_irq_map.irq_mask);
1274 static irqreturn_t malidp_se_irq(int irq, void *arg)
1276 struct drm_device *drm = arg;
1277 struct malidp_drm *malidp = drm->dev_private;
1278 struct malidp_hw_device *hwdev = malidp->dev;
1279 struct malidp_hw *hw = hwdev->hw;
1280 const struct malidp_irq_map *se = &hw->map.se_irq_map;
1284 * if we are suspended it is likely that we were invoked because
1285 * we share an interrupt line with some other driver, don't try
1286 * to read the hardware registers
1288 if (hwdev->pm_suspended)
1291 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1292 if (!(status & (se->irq_mask | se->err_mask)))
1295 #ifdef CONFIG_DEBUG_FS
1296 if (status & se->err_mask)
1297 malidp_error(malidp, &malidp->se_errors, status,
1298 drm_crtc_vblank_count(&malidp->crtc));
1300 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1303 if (status & se->vsync_irq) {
1304 switch (hwdev->mw_state) {
1306 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1309 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1310 /* disable writeback after stop */
1311 hwdev->mw_state = MW_NOT_ENABLED;
1314 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1315 /* fall through to a new start */
1317 /* writeback started, need to emulate one-shot mode */
1318 hw->disable_memwrite(hwdev);
1320 * only set config_valid HW bit if there is no other update
1321 * in progress or if we raced ahead of the DE IRQ handler
1322 * and config_valid flag will not be update until later
1324 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1325 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1326 (status & hw->map.dc_irq_map.vsync_irq))
1327 hw->set_config_valid(hwdev, 1);
1332 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1337 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1339 /* ensure interrupts are disabled */
1340 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1341 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1343 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1344 hwdev->hw->map.se_irq_map.irq_mask);
1347 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1352 int malidp_se_irq_init(struct drm_device *drm, int irq)
1354 struct malidp_drm *malidp = drm->dev_private;
1355 struct malidp_hw_device *hwdev = malidp->dev;
1358 /* ensure interrupts are disabled */
1359 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1360 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1362 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1363 malidp_se_irq_thread_handler,
1364 IRQF_SHARED, "malidp-se", drm);
1366 DRM_ERROR("failed to install SE IRQ handler\n");
1370 hwdev->mw_state = MW_NOT_ENABLED;
1371 malidp_se_irq_hw_init(hwdev);
1376 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1378 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1379 hwdev->hw->map.se_irq_map.irq_mask);