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 },
54 #define MALIDP_ID(__group, __format) \
55 ((((__group) & 0x7) << 3) | ((__format) & 0x7))
57 #define MALIDP_COMMON_FORMATS \
58 /* fourcc, layers supporting the format, internal id */ \
59 { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
60 { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
61 { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
62 { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
63 { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
64 { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
65 { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
66 { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
67 { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
68 { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
69 { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
70 { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
71 { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
72 { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
73 { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
74 { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
75 { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
76 { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
77 { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) }, \
78 { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) }, \
79 { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) }, \
80 { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }
82 static const struct malidp_format_id malidp550_de_formats[] = {
83 MALIDP_COMMON_FORMATS,
86 static const struct malidp_layer malidp500_layers[] = {
87 /* id, base address, fb pointer address base, stride offset,
88 * yuv2rgb matrix offset, mmu control register offset, rotation_features
90 { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
91 MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
92 { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
93 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
94 { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
95 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
98 static const struct malidp_layer malidp550_layers[] = {
99 /* id, base address, fb pointer address base, stride offset,
100 * yuv2rgb matrix offset, mmu control register offset, rotation_features
102 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
103 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
104 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
105 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
106 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
107 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
108 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
109 MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
112 static const struct malidp_layer malidp650_layers[] = {
113 /* id, base address, fb pointer address base, stride offset,
114 * yuv2rgb matrix offset, mmu control register offset,
117 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
118 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
119 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
120 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
121 MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
123 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
124 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
125 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
126 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
127 MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
131 #define SE_N_SCALING_COEFFS 96
132 static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
133 [MALIDP_UPSCALING_COEFFS - 1] = {
134 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
135 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
136 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
137 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
138 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
139 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
140 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
141 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
142 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
143 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
144 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
145 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
147 [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
148 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
149 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
150 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
151 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
152 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
153 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
154 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
155 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
156 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
157 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
158 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
159 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
161 [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
162 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
163 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
164 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
165 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
166 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
167 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
168 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
169 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
170 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
171 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
172 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
173 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
175 [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
176 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
177 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
178 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
179 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
180 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
181 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
182 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
183 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
184 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
185 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
186 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
187 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
189 [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
190 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
191 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
192 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
193 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
194 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
195 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
196 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
197 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
198 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
199 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
200 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
201 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
205 #define MALIDP_DE_DEFAULT_PREFETCH_START 5
207 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
209 u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
210 /* bit 4 of the CONFIG_ID register holds the line size multiplier */
211 u8 ln_size_mult = conf & 0x10 ? 2 : 1;
213 hwdev->min_line_size = 2;
214 hwdev->max_line_size = SZ_2K * ln_size_mult;
215 hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
216 hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
221 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
223 u32 status, count = 100;
225 malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
227 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
228 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
231 * entering config mode can take as long as the rendering
232 * of a full frame, hence the long sleep here
234 usleep_range(1000, 10000);
237 WARN(count == 0, "timeout while entering config mode");
240 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
242 u32 status, count = 100;
244 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
245 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
247 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
248 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
250 usleep_range(100, 1000);
253 WARN(count == 0, "timeout while leaving config mode");
256 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
260 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
261 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
267 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
270 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
272 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
275 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
279 malidp_hw_write(hwdev, hwdev->output_color_depth,
280 hwdev->hw->map.out_depth_base);
281 malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
282 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
283 val |= MALIDP500_HSYNCPOL;
284 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
285 val |= MALIDP500_VSYNCPOL;
286 val |= MALIDP_DE_DEFAULT_PREFETCH_START;
287 malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
290 * Mali-DP500 encodes the background color like this:
291 * - red @ MALIDP500_BGND_COLOR[12:0]
292 * - green @ MALIDP500_BGND_COLOR[27:16]
293 * - blue @ (MALIDP500_BGND_COLOR + 4)[12:0]
295 val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
296 (MALIDP_BGND_COLOR_R & 0xfff);
297 malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
298 malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
300 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
301 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
302 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
304 val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
305 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
306 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
308 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
309 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
310 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
312 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
313 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
315 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
316 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
318 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
321 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
324 * Each layer needs enough rotation memory to fit 8 lines
325 * worth of pixel data. Required size is then:
326 * size = rotated_width * (bpp / 8) * 8;
328 return w * drm_format_plane_cpp(fmt, 0) * 8;
331 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
337 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
339 malidp_hw_write(hwdev,
340 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
341 scaling_control + MALIDP_SE_COEFFTAB_ADDR);
342 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
343 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
344 dp500_se_scaling_coeffs[coeffs_id][i]),
345 scaling_control + MALIDP_SE_COEFFTAB_DATA);
348 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
349 struct malidp_se_config *se_config,
350 struct malidp_se_config *old_config)
352 /* Get array indices into dp500_se_scaling_coeffs. */
353 u8 h = (u8)se_config->hcoeff - 1;
354 u8 v = (u8)se_config->vcoeff - 1;
356 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
357 v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
360 if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
361 se_config->vcoeff != old_config->vcoeff)) {
362 malidp500_se_write_pp_coefftab(hwdev,
363 (MALIDP_SE_V_COEFFTAB |
364 MALIDP_SE_H_COEFFTAB),
367 if (se_config->vcoeff != old_config->vcoeff)
368 malidp500_se_write_pp_coefftab(hwdev,
369 MALIDP_SE_V_COEFFTAB,
371 if (se_config->hcoeff != old_config->hcoeff)
372 malidp500_se_write_pp_coefftab(hwdev,
373 MALIDP_SE_H_COEFFTAB,
380 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
381 struct malidp_se_config *se_config,
382 struct videomode *vm)
385 unsigned long pxlclk = vm->pixelclock; /* Hz */
386 unsigned long htotal = vm->hactive + vm->hfront_porch +
387 vm->hback_porch + vm->hsync_len;
388 unsigned long input_size = se_config->input_w * se_config->input_h;
389 unsigned long a = 10;
393 * mclk = max(a, 1.5) * pxlclk
395 * To avoid float calculaiton, using 15 instead of 1.5 and div by
398 if (se_config->scale_enable) {
399 a = 15 * input_size / (htotal * se_config->output_h);
403 mclk = a * pxlclk / 10;
404 ret = clk_get_rate(hwdev->mclk);
406 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
413 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
414 dma_addr_t *addrs, s32 *pitches,
415 int num_planes, u16 w, u16 h, u32 fmt_id,
416 const s16 *rgb2yuv_coeffs)
418 u32 base = MALIDP500_SE_MEMWRITE_BASE;
419 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
421 /* enable the scaling engine block */
422 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
424 /* restart the writeback if already enabled */
425 if (hwdev->mw_state != MW_NOT_ENABLED)
426 hwdev->mw_state = MW_RESTART;
428 hwdev->mw_state = MW_START;
430 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
431 switch (num_planes) {
433 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
434 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
435 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
438 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
439 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
440 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
443 WARN(1, "Invalid number of planes");
446 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
447 MALIDP500_SE_MEMWRITE_OUT_SIZE);
449 if (rgb2yuv_coeffs) {
452 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
453 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
454 MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
458 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
463 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
465 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
467 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
468 hwdev->mw_state = MW_STOP;
469 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
470 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
473 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
475 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
476 u8 ln_size = (conf >> 4) & 0x3, rsize;
478 hwdev->min_line_size = 2;
482 hwdev->max_line_size = SZ_2K;
483 /* two banks of 64KB for rotation memory */
487 hwdev->max_line_size = SZ_4K;
488 /* two banks of 128KB for rotation memory */
492 hwdev->max_line_size = 1280;
493 /* two banks of 40KB for rotation memory */
498 hwdev->max_line_size = 0;
502 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
506 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
508 u32 status, count = 100;
510 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
512 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
513 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
516 * entering config mode can take as long as the rendering
517 * of a full frame, hence the long sleep here
519 usleep_range(1000, 10000);
522 WARN(count == 0, "timeout while entering config mode");
525 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
527 u32 status, count = 100;
529 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
530 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
532 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
533 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
535 usleep_range(100, 1000);
538 WARN(count == 0, "timeout while leaving config mode");
541 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
545 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
546 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
552 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
555 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
557 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
560 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
562 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
564 malidp_hw_write(hwdev, hwdev->output_color_depth,
565 hwdev->hw->map.out_depth_base);
566 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
568 * Mali-DP550 and Mali-DP650 encode the background color like this:
569 * - red @ MALIDP550_DE_BGND_COLOR[23:16]
570 * - green @ MALIDP550_DE_BGND_COLOR[15:8]
571 * - blue @ MALIDP550_DE_BGND_COLOR[7:0]
573 * We need to truncate the least significant 4 bits from the default
574 * MALIDP_BGND_COLOR_x values
576 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
577 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
578 ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
579 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
581 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
582 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
583 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
585 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
586 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
587 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
589 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
590 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
591 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
592 val |= MALIDP550_HSYNCPOL;
593 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
594 val |= MALIDP550_VSYNCPOL;
595 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
597 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
598 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
600 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
601 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
603 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
606 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
611 /* 8 lines at 4 bytes per pixel */
612 case DRM_FORMAT_ARGB2101010:
613 case DRM_FORMAT_ABGR2101010:
614 case DRM_FORMAT_RGBA1010102:
615 case DRM_FORMAT_BGRA1010102:
616 case DRM_FORMAT_ARGB8888:
617 case DRM_FORMAT_ABGR8888:
618 case DRM_FORMAT_RGBA8888:
619 case DRM_FORMAT_BGRA8888:
620 case DRM_FORMAT_XRGB8888:
621 case DRM_FORMAT_XBGR8888:
622 case DRM_FORMAT_RGBX8888:
623 case DRM_FORMAT_BGRX8888:
624 case DRM_FORMAT_RGB888:
625 case DRM_FORMAT_BGR888:
626 /* 16 lines at 2 bytes per pixel */
627 case DRM_FORMAT_RGBA5551:
628 case DRM_FORMAT_ABGR1555:
629 case DRM_FORMAT_RGB565:
630 case DRM_FORMAT_BGR565:
631 case DRM_FORMAT_UYVY:
632 case DRM_FORMAT_YUYV:
635 /* 16 lines at 1.5 bytes per pixel */
636 case DRM_FORMAT_NV12:
637 case DRM_FORMAT_YUV420:
644 return w * bytes_per_col;
647 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
648 struct malidp_se_config *se_config,
649 struct malidp_se_config *old_config)
651 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
652 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
653 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
654 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
656 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
657 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
661 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
662 struct malidp_se_config *se_config,
663 struct videomode *vm)
666 unsigned long pxlclk = vm->pixelclock;
667 unsigned long htotal = vm->hactive + vm->hfront_porch +
668 vm->hback_porch + vm->hsync_len;
669 unsigned long numerator = 1, denominator = 1;
672 if (se_config->scale_enable) {
673 numerator = max(se_config->input_w, se_config->output_w) *
675 numerator += se_config->output_w *
676 (se_config->output_h -
677 min(se_config->input_h, se_config->output_h));
678 denominator = (htotal - 2) * se_config->output_h;
681 /* mclk can't be slower than pxlclk. */
682 if (numerator < denominator)
683 numerator = denominator = 1;
684 mclk = (pxlclk * numerator) / denominator;
685 ret = clk_get_rate(hwdev->mclk);
687 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
694 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
695 dma_addr_t *addrs, s32 *pitches,
696 int num_planes, u16 w, u16 h, u32 fmt_id,
697 const s16 *rgb2yuv_coeffs)
699 u32 base = MALIDP550_SE_MEMWRITE_BASE;
700 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
702 /* enable the scaling engine block */
703 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
705 hwdev->mw_state = MW_ONESHOT;
707 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
708 switch (num_planes) {
710 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
711 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
712 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
715 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
716 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
717 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
720 WARN(1, "Invalid number of planes");
723 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
724 MALIDP550_SE_MEMWRITE_OUT_SIZE);
725 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
726 MALIDP550_SE_CONTROL);
728 if (rgb2yuv_coeffs) {
731 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
732 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
733 MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
740 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
742 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
744 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
745 MALIDP550_SE_CONTROL);
746 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
749 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
751 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
752 u8 ln_size = (conf >> 4) & 0x3, rsize;
754 hwdev->min_line_size = 4;
759 /* reserved values */
760 hwdev->max_line_size = 0;
763 hwdev->max_line_size = SZ_4K;
764 /* two banks of 128KB for rotation memory */
768 hwdev->max_line_size = 2560;
769 /* two banks of 80KB for rotation memory */
773 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
777 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
780 .coeffs_base = MALIDP500_COEFFS_BASE,
781 .se_base = MALIDP500_SE_BASE,
782 .dc_base = MALIDP500_DC_BASE,
783 .out_depth_base = MALIDP500_OUTPUT_DEPTH,
784 .features = 0, /* no CLEARIRQ register */
785 .n_layers = ARRAY_SIZE(malidp500_layers),
786 .layers = malidp500_layers,
788 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
789 MALIDP500_DE_IRQ_AXI_ERR |
790 MALIDP500_DE_IRQ_VSYNC |
791 MALIDP500_DE_IRQ_GLOBAL,
792 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
793 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
794 MALIDP500_DE_IRQ_AXI_ERR |
795 MALIDP500_DE_IRQ_SATURATION,
798 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
799 MALIDP500_SE_IRQ_CONF_VALID |
800 MALIDP500_SE_IRQ_GLOBAL,
801 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
802 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
803 MALIDP500_SE_IRQ_AXI_ERROR |
804 MALIDP500_SE_IRQ_OVERRUN,
807 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
808 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
810 .pixel_formats = malidp500_de_formats,
811 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
812 .bus_align_bytes = 8,
814 .query_hw = malidp500_query_hw,
815 .enter_config_mode = malidp500_enter_config_mode,
816 .leave_config_mode = malidp500_leave_config_mode,
817 .in_config_mode = malidp500_in_config_mode,
818 .set_config_valid = malidp500_set_config_valid,
819 .modeset = malidp500_modeset,
820 .rotmem_required = malidp500_rotmem_required,
821 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
822 .se_calc_mclk = malidp500_se_calc_mclk,
823 .enable_memwrite = malidp500_enable_memwrite,
824 .disable_memwrite = malidp500_disable_memwrite,
825 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
829 .coeffs_base = MALIDP550_COEFFS_BASE,
830 .se_base = MALIDP550_SE_BASE,
831 .dc_base = MALIDP550_DC_BASE,
832 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
833 .features = MALIDP_REGMAP_HAS_CLEARIRQ,
834 .n_layers = ARRAY_SIZE(malidp550_layers),
835 .layers = malidp550_layers,
837 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
838 MALIDP550_DE_IRQ_VSYNC,
839 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
840 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
841 MALIDP550_DE_IRQ_SATURATION |
842 MALIDP550_DE_IRQ_AXI_ERR,
845 .irq_mask = MALIDP550_SE_IRQ_EOW,
846 .vsync_irq = MALIDP550_SE_IRQ_EOW,
847 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
848 MALIDP550_SE_IRQ_OVR |
849 MALIDP550_SE_IRQ_IBSY,
852 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
854 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
856 .pixel_formats = malidp550_de_formats,
857 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
858 .bus_align_bytes = 8,
860 .query_hw = malidp550_query_hw,
861 .enter_config_mode = malidp550_enter_config_mode,
862 .leave_config_mode = malidp550_leave_config_mode,
863 .in_config_mode = malidp550_in_config_mode,
864 .set_config_valid = malidp550_set_config_valid,
865 .modeset = malidp550_modeset,
866 .rotmem_required = malidp550_rotmem_required,
867 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
868 .se_calc_mclk = malidp550_se_calc_mclk,
869 .enable_memwrite = malidp550_enable_memwrite,
870 .disable_memwrite = malidp550_disable_memwrite,
875 .coeffs_base = MALIDP550_COEFFS_BASE,
876 .se_base = MALIDP550_SE_BASE,
877 .dc_base = MALIDP550_DC_BASE,
878 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
879 .features = MALIDP_REGMAP_HAS_CLEARIRQ,
880 .n_layers = ARRAY_SIZE(malidp650_layers),
881 .layers = malidp650_layers,
883 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
884 MALIDP650_DE_IRQ_DRIFT |
885 MALIDP550_DE_IRQ_VSYNC,
886 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
887 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
888 MALIDP650_DE_IRQ_DRIFT |
889 MALIDP550_DE_IRQ_SATURATION |
890 MALIDP550_DE_IRQ_AXI_ERR |
891 MALIDP650_DE_IRQ_ACEV1 |
892 MALIDP650_DE_IRQ_ACEV2 |
893 MALIDP650_DE_IRQ_ACEG |
894 MALIDP650_DE_IRQ_AXIEP,
897 .irq_mask = MALIDP550_SE_IRQ_EOW,
898 .vsync_irq = MALIDP550_SE_IRQ_EOW,
899 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
900 MALIDP550_SE_IRQ_OVR |
901 MALIDP550_SE_IRQ_IBSY,
904 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
906 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
908 .pixel_formats = malidp550_de_formats,
909 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
910 .bus_align_bytes = 16,
912 .query_hw = malidp650_query_hw,
913 .enter_config_mode = malidp550_enter_config_mode,
914 .leave_config_mode = malidp550_leave_config_mode,
915 .in_config_mode = malidp550_in_config_mode,
916 .set_config_valid = malidp550_set_config_valid,
917 .modeset = malidp550_modeset,
918 .rotmem_required = malidp550_rotmem_required,
919 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
920 .se_calc_mclk = malidp550_se_calc_mclk,
921 .enable_memwrite = malidp550_enable_memwrite,
922 .disable_memwrite = malidp550_disable_memwrite,
927 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
928 u8 layer_id, u32 format)
932 for (i = 0; i < map->n_pixel_formats; i++) {
933 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
934 (map->pixel_formats[i].format == format))
935 return map->pixel_formats[i].id;
938 return MALIDP_INVALID_FORMAT_ID;
941 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
943 u32 base = malidp_get_block_base(hwdev, block);
945 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
946 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
948 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
951 static irqreturn_t malidp_de_irq(int irq, void *arg)
953 struct drm_device *drm = arg;
954 struct malidp_drm *malidp = drm->dev_private;
955 struct malidp_hw_device *hwdev;
956 struct malidp_hw *hw;
957 const struct malidp_irq_map *de;
958 u32 status, mask, dc_status;
959 irqreturn_t ret = IRQ_NONE;
963 de = &hw->map.de_irq_map;
966 * if we are suspended it is likely that we were invoked because
967 * we share an interrupt line with some other driver, don't try
968 * to read the hardware registers
970 if (hwdev->pm_suspended)
973 /* first handle the config valid IRQ */
974 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
975 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
976 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
977 /* do we have a page flip event? */
978 if (malidp->event != NULL) {
979 spin_lock(&drm->event_lock);
980 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
981 malidp->event = NULL;
982 spin_unlock(&drm->event_lock);
984 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
985 ret = IRQ_WAKE_THREAD;
988 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
989 if (!(status & de->irq_mask))
992 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
993 /* keep the status of the enabled interrupts, plus the error bits */
994 status &= (mask | de->err_mask);
995 if ((status & de->vsync_irq) && malidp->crtc.enabled)
996 drm_crtc_handle_vblank(&malidp->crtc);
998 #ifdef CONFIG_DEBUG_FS
999 if (status & de->err_mask) {
1000 malidp_error(malidp, &malidp->de_errors, status,
1001 drm_crtc_vblank_count(&malidp->crtc));
1004 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1006 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1009 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1011 struct drm_device *drm = arg;
1012 struct malidp_drm *malidp = drm->dev_private;
1014 wake_up(&malidp->wq);
1019 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1021 /* ensure interrupts are disabled */
1022 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1023 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1024 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1025 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1027 /* first enable the DC block IRQs */
1028 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1029 hwdev->hw->map.dc_irq_map.irq_mask);
1031 /* now enable the DE block IRQs */
1032 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1033 hwdev->hw->map.de_irq_map.irq_mask);
1036 int malidp_de_irq_init(struct drm_device *drm, int irq)
1038 struct malidp_drm *malidp = drm->dev_private;
1039 struct malidp_hw_device *hwdev = malidp->dev;
1042 /* ensure interrupts are disabled */
1043 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1044 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1045 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1046 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1048 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1049 malidp_de_irq_thread_handler,
1050 IRQF_SHARED, "malidp-de", drm);
1052 DRM_ERROR("failed to install DE IRQ handler\n");
1056 malidp_de_irq_hw_init(hwdev);
1061 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1063 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1064 hwdev->hw->map.de_irq_map.irq_mask);
1065 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1066 hwdev->hw->map.dc_irq_map.irq_mask);
1069 static irqreturn_t malidp_se_irq(int irq, void *arg)
1071 struct drm_device *drm = arg;
1072 struct malidp_drm *malidp = drm->dev_private;
1073 struct malidp_hw_device *hwdev = malidp->dev;
1074 struct malidp_hw *hw = hwdev->hw;
1075 const struct malidp_irq_map *se = &hw->map.se_irq_map;
1079 * if we are suspended it is likely that we were invoked because
1080 * we share an interrupt line with some other driver, don't try
1081 * to read the hardware registers
1083 if (hwdev->pm_suspended)
1086 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1087 if (!(status & (se->irq_mask | se->err_mask)))
1090 #ifdef CONFIG_DEBUG_FS
1091 if (status & se->err_mask)
1092 malidp_error(malidp, &malidp->se_errors, status,
1093 drm_crtc_vblank_count(&malidp->crtc));
1095 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1098 if (status & se->vsync_irq) {
1099 switch (hwdev->mw_state) {
1101 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1104 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1105 /* disable writeback after stop */
1106 hwdev->mw_state = MW_NOT_ENABLED;
1109 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1110 /* fall through to a new start */
1112 /* writeback started, need to emulate one-shot mode */
1113 hw->disable_memwrite(hwdev);
1115 * only set config_valid HW bit if there is no other update
1116 * in progress or if we raced ahead of the DE IRQ handler
1117 * and config_valid flag will not be update until later
1119 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1120 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1121 (status & hw->map.dc_irq_map.vsync_irq))
1122 hw->set_config_valid(hwdev, 1);
1127 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1132 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1134 /* ensure interrupts are disabled */
1135 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1136 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1138 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1139 hwdev->hw->map.se_irq_map.irq_mask);
1142 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1147 int malidp_se_irq_init(struct drm_device *drm, int irq)
1149 struct malidp_drm *malidp = drm->dev_private;
1150 struct malidp_hw_device *hwdev = malidp->dev;
1153 /* ensure interrupts are disabled */
1154 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1155 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1157 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1158 malidp_se_irq_thread_handler,
1159 IRQF_SHARED, "malidp-se", drm);
1161 DRM_ERROR("failed to install SE IRQ handler\n");
1165 hwdev->mw_state = MW_NOT_ENABLED;
1166 malidp_se_irq_hw_init(hwdev);
1171 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1173 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1174 hwdev->hw->map.se_irq_map.irq_mask);