1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/clk.h>
16#include <linux/types.h>
17#include <linux/io.h>
18#include <drm/drmP.h>
19#include <video/videomode.h>
20#include <video/display_timing.h>
21
22#include "malidp_drv.h"
23#include "malidp_hw.h"
24#include "malidp_mw.h"
25
26enum {
27 MW_NOT_ENABLED = 0,
28 MW_ONESHOT,
29 MW_START,
30 MW_RESTART,
31 MW_STOP,
32};
33
34static const struct malidp_format_id malidp500_de_formats[] = {
35
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};
53
54#define MALIDP_ID(__group, __format) \
55 ((((__group) & 0x7) << 3) | ((__format) & 0x7))
56
57#define MALIDP_COMMON_FORMATS \
58 \
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) }, \
81 { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}
82
83static const struct malidp_format_id malidp550_de_formats[] = {
84 MALIDP_COMMON_FORMATS,
85};
86
87static const struct malidp_format_id malidp650_de_formats[] = {
88 MALIDP_COMMON_FORMATS,
89 { DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)},
90};
91
92static const struct malidp_layer malidp500_layers[] = {
93
94
95
96 { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
97 MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
98 { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
99 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
100 { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
101 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
102};
103
104static const struct malidp_layer malidp550_layers[] = {
105
106
107
108 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
109 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
110 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
111 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
112 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
113 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
114 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
115 MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
116};
117
118static const struct malidp_layer malidp650_layers[] = {
119
120
121
122
123 { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
124 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
125 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
126 { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
127 MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
128 ROTATE_COMPRESSED },
129 { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
130 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
131 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
132 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
133 MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
134 ROTATE_NONE },
135};
136
137#define SE_N_SCALING_COEFFS 96
138static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
139 [MALIDP_UPSCALING_COEFFS - 1] = {
140 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
141 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
142 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
143 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
144 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
145 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
146 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
147 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
148 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
149 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
150 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
151 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
152 },
153 [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
154 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
155 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
156 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
157 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
158 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
159 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
160 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
161 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
162 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
163 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
164 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
165 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
166 },
167 [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
168 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
169 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
170 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
171 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
172 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
173 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
174 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
175 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
176 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
177 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
178 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
179 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
180 },
181 [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
182 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
183 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
184 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
185 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
186 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
187 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
188 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
189 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
190 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
191 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
192 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
193 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
194 },
195 [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
196 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
197 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
198 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
199 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
200 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
201 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
202 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
203 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
204 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
205 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
206 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
207 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
208 },
209};
210
211#define MALIDP_DE_DEFAULT_PREFETCH_START 5
212
213static int malidp500_query_hw(struct malidp_hw_device *hwdev)
214{
215 u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
216
217 u8 ln_size_mult = conf & 0x10 ? 2 : 1;
218
219 hwdev->min_line_size = 2;
220 hwdev->max_line_size = SZ_2K * ln_size_mult;
221 hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
222 hwdev->rotation_memory[1] = 0;
223
224 return 0;
225}
226
227static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
228{
229 u32 status, count = 100;
230
231 malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
232 while (count) {
233 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
234 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
235 break;
236
237
238
239
240 usleep_range(1000, 10000);
241 count--;
242 }
243 WARN(count == 0, "timeout while entering config mode");
244}
245
246static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
247{
248 u32 status, count = 100;
249
250 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
251 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
252 while (count) {
253 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
254 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
255 break;
256 usleep_range(100, 1000);
257 count--;
258 }
259 WARN(count == 0, "timeout while leaving config mode");
260}
261
262static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
263{
264 u32 status;
265
266 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
267 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
268 return true;
269
270 return false;
271}
272
273static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
274{
275 if (value)
276 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
277 else
278 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
279}
280
281static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
282{
283 u32 val = 0;
284
285 malidp_hw_write(hwdev, hwdev->output_color_depth,
286 hwdev->hw->map.out_depth_base);
287 malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
288 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
289 val |= MALIDP500_HSYNCPOL;
290 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
291 val |= MALIDP500_VSYNCPOL;
292 val |= MALIDP_DE_DEFAULT_PREFETCH_START;
293 malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
294
295
296
297
298
299
300
301 val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
302 (MALIDP_BGND_COLOR_R & 0xfff);
303 malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
304 malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
305
306 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
307 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
308 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
309
310 val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
311 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
312 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
313
314 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
315 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
316 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
317
318 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
319 malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
320
321 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
322 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
323 else
324 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
325}
326
327static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
328{
329
330
331
332
333
334 return w * drm_format_plane_cpp(fmt, 0) * 8;
335}
336
337static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
338 u32 direction,
339 u16 addr,
340 u8 coeffs_id)
341{
342 int i;
343 u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
344
345 malidp_hw_write(hwdev,
346 direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
347 scaling_control + MALIDP_SE_COEFFTAB_ADDR);
348 for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
349 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
350 dp500_se_scaling_coeffs[coeffs_id][i]),
351 scaling_control + MALIDP_SE_COEFFTAB_DATA);
352}
353
354static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
355 struct malidp_se_config *se_config,
356 struct malidp_se_config *old_config)
357{
358
359 u8 h = (u8)se_config->hcoeff - 1;
360 u8 v = (u8)se_config->vcoeff - 1;
361
362 if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
363 v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
364 return -EINVAL;
365
366 if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
367 se_config->vcoeff != old_config->vcoeff)) {
368 malidp500_se_write_pp_coefftab(hwdev,
369 (MALIDP_SE_V_COEFFTAB |
370 MALIDP_SE_H_COEFFTAB),
371 0, v);
372 } else {
373 if (se_config->vcoeff != old_config->vcoeff)
374 malidp500_se_write_pp_coefftab(hwdev,
375 MALIDP_SE_V_COEFFTAB,
376 0, v);
377 if (se_config->hcoeff != old_config->hcoeff)
378 malidp500_se_write_pp_coefftab(hwdev,
379 MALIDP_SE_H_COEFFTAB,
380 0, h);
381 }
382
383 return 0;
384}
385
386static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
387 struct malidp_se_config *se_config,
388 struct videomode *vm)
389{
390 unsigned long mclk;
391 unsigned long pxlclk = vm->pixelclock;
392 unsigned long htotal = vm->hactive + vm->hfront_porch +
393 vm->hback_porch + vm->hsync_len;
394 unsigned long input_size = se_config->input_w * se_config->input_h;
395 unsigned long a = 10;
396 long ret;
397
398
399
400
401
402
403
404 if (se_config->scale_enable) {
405 a = 15 * input_size / (htotal * se_config->output_h);
406 if (a < 15)
407 a = 15;
408 }
409 mclk = a * pxlclk / 10;
410 ret = clk_get_rate(hwdev->mclk);
411 if (ret < mclk) {
412 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
413 mclk / 1000);
414 return -EINVAL;
415 }
416 return ret;
417}
418
419static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
420 dma_addr_t *addrs, s32 *pitches,
421 int num_planes, u16 w, u16 h, u32 fmt_id,
422 const s16 *rgb2yuv_coeffs)
423{
424 u32 base = MALIDP500_SE_MEMWRITE_BASE;
425 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
426
427
428 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
429
430
431 if (hwdev->mw_state != MW_NOT_ENABLED)
432 hwdev->mw_state = MW_RESTART;
433 else
434 hwdev->mw_state = MW_START;
435
436 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
437 switch (num_planes) {
438 case 2:
439 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
440 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
441 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
442
443 case 1:
444 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
445 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
446 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
447 break;
448 default:
449 WARN(1, "Invalid number of planes");
450 }
451
452 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
453 MALIDP500_SE_MEMWRITE_OUT_SIZE);
454
455 if (rgb2yuv_coeffs) {
456 int i;
457
458 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
459 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
460 MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
461 }
462 }
463
464 malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
465
466 return 0;
467}
468
469static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
470{
471 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
472
473 if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
474 hwdev->mw_state = MW_STOP;
475 malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
476 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
477}
478
479static int malidp550_query_hw(struct malidp_hw_device *hwdev)
480{
481 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
482 u8 ln_size = (conf >> 4) & 0x3, rsize;
483
484 hwdev->min_line_size = 2;
485
486 switch (ln_size) {
487 case 0:
488 hwdev->max_line_size = SZ_2K;
489
490 rsize = 64;
491 break;
492 case 1:
493 hwdev->max_line_size = SZ_4K;
494
495 rsize = 128;
496 break;
497 case 2:
498 hwdev->max_line_size = 1280;
499
500 rsize = 40;
501 break;
502 case 3:
503
504 hwdev->max_line_size = 0;
505 return -EINVAL;
506 }
507
508 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
509 return 0;
510}
511
512static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
513{
514 u32 status, count = 100;
515
516 malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
517 while (count) {
518 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
519 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
520 break;
521
522
523
524
525 usleep_range(1000, 10000);
526 count--;
527 }
528 WARN(count == 0, "timeout while entering config mode");
529}
530
531static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
532{
533 u32 status, count = 100;
534
535 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
536 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
537 while (count) {
538 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
539 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
540 break;
541 usleep_range(100, 1000);
542 count--;
543 }
544 WARN(count == 0, "timeout while leaving config mode");
545}
546
547static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
548{
549 u32 status;
550
551 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
552 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
553 return true;
554
555 return false;
556}
557
558static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
559{
560 if (value)
561 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
562 else
563 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
564}
565
566static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
567{
568 u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
569
570 malidp_hw_write(hwdev, hwdev->output_color_depth,
571 hwdev->hw->map.out_depth_base);
572 malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
573
574
575
576
577
578
579
580
581
582 val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
583 (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
584 ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
585 malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
586
587 val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
588 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
589 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
590
591 val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
592 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
593 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
594
595 val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
596 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
597 if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
598 val |= MALIDP550_HSYNCPOL;
599 if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
600 val |= MALIDP550_VSYNCPOL;
601 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
602
603 val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
604 malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
605
606 if (mode->flags & DISPLAY_FLAGS_INTERLACED)
607 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
608 else
609 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
610}
611
612static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
613{
614 u32 bytes_per_col;
615
616 switch (fmt) {
617
618 case DRM_FORMAT_ARGB2101010:
619 case DRM_FORMAT_ABGR2101010:
620 case DRM_FORMAT_RGBA1010102:
621 case DRM_FORMAT_BGRA1010102:
622 case DRM_FORMAT_ARGB8888:
623 case DRM_FORMAT_ABGR8888:
624 case DRM_FORMAT_RGBA8888:
625 case DRM_FORMAT_BGRA8888:
626 case DRM_FORMAT_XRGB8888:
627 case DRM_FORMAT_XBGR8888:
628 case DRM_FORMAT_RGBX8888:
629 case DRM_FORMAT_BGRX8888:
630 case DRM_FORMAT_RGB888:
631 case DRM_FORMAT_BGR888:
632
633 case DRM_FORMAT_RGBA5551:
634 case DRM_FORMAT_ABGR1555:
635 case DRM_FORMAT_RGB565:
636 case DRM_FORMAT_BGR565:
637 case DRM_FORMAT_UYVY:
638 case DRM_FORMAT_YUYV:
639 case DRM_FORMAT_X0L0:
640 case DRM_FORMAT_X0L2:
641 bytes_per_col = 32;
642 break;
643
644 case DRM_FORMAT_NV12:
645 case DRM_FORMAT_YUV420:
646 bytes_per_col = 24;
647 break;
648 default:
649 return -EINVAL;
650 }
651
652 return w * bytes_per_col;
653}
654
655static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
656 struct malidp_se_config *se_config,
657 struct malidp_se_config *old_config)
658{
659 u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
660 MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
661 u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
662 MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
663
664 malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
665 malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
666 return 0;
667}
668
669static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
670 struct malidp_se_config *se_config,
671 struct videomode *vm)
672{
673 unsigned long mclk;
674 unsigned long pxlclk = vm->pixelclock;
675 unsigned long htotal = vm->hactive + vm->hfront_porch +
676 vm->hback_porch + vm->hsync_len;
677 unsigned long numerator = 1, denominator = 1;
678 long ret;
679
680 if (se_config->scale_enable) {
681 numerator = max(se_config->input_w, se_config->output_w) *
682 se_config->input_h;
683 numerator += se_config->output_w *
684 (se_config->output_h -
685 min(se_config->input_h, se_config->output_h));
686 denominator = (htotal - 2) * se_config->output_h;
687 }
688
689
690 if (numerator < denominator)
691 numerator = denominator = 1;
692 mclk = (pxlclk * numerator) / denominator;
693 ret = clk_get_rate(hwdev->mclk);
694 if (ret < mclk) {
695 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
696 mclk / 1000);
697 return -EINVAL;
698 }
699 return ret;
700}
701
702static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
703 dma_addr_t *addrs, s32 *pitches,
704 int num_planes, u16 w, u16 h, u32 fmt_id,
705 const s16 *rgb2yuv_coeffs)
706{
707 u32 base = MALIDP550_SE_MEMWRITE_BASE;
708 u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
709
710
711 malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
712
713 hwdev->mw_state = MW_ONESHOT;
714
715 malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
716 switch (num_planes) {
717 case 2:
718 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
719 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
720 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
721
722 case 1:
723 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
724 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
725 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
726 break;
727 default:
728 WARN(1, "Invalid number of planes");
729 }
730
731 malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
732 MALIDP550_SE_MEMWRITE_OUT_SIZE);
733 malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
734 MALIDP550_SE_CONTROL);
735
736 if (rgb2yuv_coeffs) {
737 int i;
738
739 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
740 malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
741 MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
742 }
743 }
744
745 return 0;
746}
747
748static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
749{
750 u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
751
752 malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
753 MALIDP550_SE_CONTROL);
754 malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
755}
756
757static int malidp650_query_hw(struct malidp_hw_device *hwdev)
758{
759 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
760 u8 ln_size = (conf >> 4) & 0x3, rsize;
761
762 hwdev->min_line_size = 4;
763
764 switch (ln_size) {
765 case 0:
766 case 2:
767
768 hwdev->max_line_size = 0;
769 return -EINVAL;
770 case 1:
771 hwdev->max_line_size = SZ_4K;
772
773 rsize = 128;
774 break;
775 case 3:
776 hwdev->max_line_size = 2560;
777
778 rsize = 80;
779 }
780
781 hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
782 return 0;
783}
784
785const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
786 [MALIDP_500] = {
787 .map = {
788 .coeffs_base = MALIDP500_COEFFS_BASE,
789 .se_base = MALIDP500_SE_BASE,
790 .dc_base = MALIDP500_DC_BASE,
791 .out_depth_base = MALIDP500_OUTPUT_DEPTH,
792 .features = 0,
793 .n_layers = ARRAY_SIZE(malidp500_layers),
794 .layers = malidp500_layers,
795 .de_irq_map = {
796 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
797 MALIDP500_DE_IRQ_AXI_ERR |
798 MALIDP500_DE_IRQ_VSYNC |
799 MALIDP500_DE_IRQ_GLOBAL,
800 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
801 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
802 MALIDP500_DE_IRQ_AXI_ERR |
803 MALIDP500_DE_IRQ_SATURATION,
804 },
805 .se_irq_map = {
806 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
807 MALIDP500_SE_IRQ_CONF_VALID |
808 MALIDP500_SE_IRQ_GLOBAL,
809 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
810 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
811 MALIDP500_SE_IRQ_AXI_ERROR |
812 MALIDP500_SE_IRQ_OVERRUN,
813 },
814 .dc_irq_map = {
815 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
816 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
817 },
818 .pixel_formats = malidp500_de_formats,
819 .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
820 .bus_align_bytes = 8,
821 },
822 .query_hw = malidp500_query_hw,
823 .enter_config_mode = malidp500_enter_config_mode,
824 .leave_config_mode = malidp500_leave_config_mode,
825 .in_config_mode = malidp500_in_config_mode,
826 .set_config_valid = malidp500_set_config_valid,
827 .modeset = malidp500_modeset,
828 .rotmem_required = malidp500_rotmem_required,
829 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
830 .se_calc_mclk = malidp500_se_calc_mclk,
831 .enable_memwrite = malidp500_enable_memwrite,
832 .disable_memwrite = malidp500_disable_memwrite,
833 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
834 },
835 [MALIDP_550] = {
836 .map = {
837 .coeffs_base = MALIDP550_COEFFS_BASE,
838 .se_base = MALIDP550_SE_BASE,
839 .dc_base = MALIDP550_DC_BASE,
840 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
841 .features = MALIDP_REGMAP_HAS_CLEARIRQ,
842 .n_layers = ARRAY_SIZE(malidp550_layers),
843 .layers = malidp550_layers,
844 .de_irq_map = {
845 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
846 MALIDP550_DE_IRQ_VSYNC,
847 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
848 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
849 MALIDP550_DE_IRQ_SATURATION |
850 MALIDP550_DE_IRQ_AXI_ERR,
851 },
852 .se_irq_map = {
853 .irq_mask = MALIDP550_SE_IRQ_EOW,
854 .vsync_irq = MALIDP550_SE_IRQ_EOW,
855 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
856 MALIDP550_SE_IRQ_OVR |
857 MALIDP550_SE_IRQ_IBSY,
858 },
859 .dc_irq_map = {
860 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
861 MALIDP550_DC_IRQ_SE,
862 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
863 },
864 .pixel_formats = malidp550_de_formats,
865 .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
866 .bus_align_bytes = 8,
867 },
868 .query_hw = malidp550_query_hw,
869 .enter_config_mode = malidp550_enter_config_mode,
870 .leave_config_mode = malidp550_leave_config_mode,
871 .in_config_mode = malidp550_in_config_mode,
872 .set_config_valid = malidp550_set_config_valid,
873 .modeset = malidp550_modeset,
874 .rotmem_required = malidp550_rotmem_required,
875 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
876 .se_calc_mclk = malidp550_se_calc_mclk,
877 .enable_memwrite = malidp550_enable_memwrite,
878 .disable_memwrite = malidp550_disable_memwrite,
879 .features = 0,
880 },
881 [MALIDP_650] = {
882 .map = {
883 .coeffs_base = MALIDP550_COEFFS_BASE,
884 .se_base = MALIDP550_SE_BASE,
885 .dc_base = MALIDP550_DC_BASE,
886 .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
887 .features = MALIDP_REGMAP_HAS_CLEARIRQ,
888 .n_layers = ARRAY_SIZE(malidp650_layers),
889 .layers = malidp650_layers,
890 .de_irq_map = {
891 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
892 MALIDP650_DE_IRQ_DRIFT |
893 MALIDP550_DE_IRQ_VSYNC,
894 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
895 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
896 MALIDP650_DE_IRQ_DRIFT |
897 MALIDP550_DE_IRQ_SATURATION |
898 MALIDP550_DE_IRQ_AXI_ERR |
899 MALIDP650_DE_IRQ_ACEV1 |
900 MALIDP650_DE_IRQ_ACEV2 |
901 MALIDP650_DE_IRQ_ACEG |
902 MALIDP650_DE_IRQ_AXIEP,
903 },
904 .se_irq_map = {
905 .irq_mask = MALIDP550_SE_IRQ_EOW,
906 .vsync_irq = MALIDP550_SE_IRQ_EOW,
907 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
908 MALIDP550_SE_IRQ_OVR |
909 MALIDP550_SE_IRQ_IBSY,
910 },
911 .dc_irq_map = {
912 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
913 MALIDP550_DC_IRQ_SE,
914 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
915 },
916 .pixel_formats = malidp650_de_formats,
917 .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
918 .bus_align_bytes = 16,
919 },
920 .query_hw = malidp650_query_hw,
921 .enter_config_mode = malidp550_enter_config_mode,
922 .leave_config_mode = malidp550_leave_config_mode,
923 .in_config_mode = malidp550_in_config_mode,
924 .set_config_valid = malidp550_set_config_valid,
925 .modeset = malidp550_modeset,
926 .rotmem_required = malidp550_rotmem_required,
927 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
928 .se_calc_mclk = malidp550_se_calc_mclk,
929 .enable_memwrite = malidp550_enable_memwrite,
930 .disable_memwrite = malidp550_disable_memwrite,
931 .features = 0,
932 },
933};
934
935u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
936 u8 layer_id, u32 format)
937{
938 unsigned int i;
939
940 for (i = 0; i < map->n_pixel_formats; i++) {
941 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
942 (map->pixel_formats[i].format == format))
943 return map->pixel_formats[i].id;
944 }
945
946 return MALIDP_INVALID_FORMAT_ID;
947}
948
949static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
950{
951 u32 base = malidp_get_block_base(hwdev, block);
952
953 if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
954 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
955 else
956 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
957}
958
959static irqreturn_t malidp_de_irq(int irq, void *arg)
960{
961 struct drm_device *drm = arg;
962 struct malidp_drm *malidp = drm->dev_private;
963 struct malidp_hw_device *hwdev;
964 struct malidp_hw *hw;
965 const struct malidp_irq_map *de;
966 u32 status, mask, dc_status;
967 irqreturn_t ret = IRQ_NONE;
968
969 hwdev = malidp->dev;
970 hw = hwdev->hw;
971 de = &hw->map.de_irq_map;
972
973
974
975
976
977
978 if (hwdev->pm_suspended)
979 return IRQ_NONE;
980
981
982 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
983 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
984 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
985
986 if (malidp->event != NULL) {
987 spin_lock(&drm->event_lock);
988 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
989 malidp->event = NULL;
990 spin_unlock(&drm->event_lock);
991 }
992 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
993 ret = IRQ_WAKE_THREAD;
994 }
995
996 status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
997 if (!(status & de->irq_mask))
998 return ret;
999
1000 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1001
1002 status &= (mask | de->err_mask);
1003 if ((status & de->vsync_irq) && malidp->crtc.enabled)
1004 drm_crtc_handle_vblank(&malidp->crtc);
1005
1006#ifdef CONFIG_DEBUG_FS
1007 if (status & de->err_mask) {
1008 malidp_error(malidp, &malidp->de_errors, status,
1009 drm_crtc_vblank_count(&malidp->crtc));
1010 }
1011#endif
1012 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1013
1014 return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1015}
1016
1017static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1018{
1019 struct drm_device *drm = arg;
1020 struct malidp_drm *malidp = drm->dev_private;
1021
1022 wake_up(&malidp->wq);
1023
1024 return IRQ_HANDLED;
1025}
1026
1027void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1028{
1029
1030 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1031 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1032 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1033 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1034
1035
1036 malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1037 hwdev->hw->map.dc_irq_map.irq_mask);
1038
1039
1040 malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1041 hwdev->hw->map.de_irq_map.irq_mask);
1042}
1043
1044int malidp_de_irq_init(struct drm_device *drm, int irq)
1045{
1046 struct malidp_drm *malidp = drm->dev_private;
1047 struct malidp_hw_device *hwdev = malidp->dev;
1048 int ret;
1049
1050
1051 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1052 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1053 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1054 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1055
1056 ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1057 malidp_de_irq_thread_handler,
1058 IRQF_SHARED, "malidp-de", drm);
1059 if (ret < 0) {
1060 DRM_ERROR("failed to install DE IRQ handler\n");
1061 return ret;
1062 }
1063
1064 malidp_de_irq_hw_init(hwdev);
1065
1066 return 0;
1067}
1068
1069void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1070{
1071 malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1072 hwdev->hw->map.de_irq_map.irq_mask);
1073 malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1074 hwdev->hw->map.dc_irq_map.irq_mask);
1075}
1076
1077static irqreturn_t malidp_se_irq(int irq, void *arg)
1078{
1079 struct drm_device *drm = arg;
1080 struct malidp_drm *malidp = drm->dev_private;
1081 struct malidp_hw_device *hwdev = malidp->dev;
1082 struct malidp_hw *hw = hwdev->hw;
1083 const struct malidp_irq_map *se = &hw->map.se_irq_map;
1084 u32 status, mask;
1085
1086
1087
1088
1089
1090
1091 if (hwdev->pm_suspended)
1092 return IRQ_NONE;
1093
1094 status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1095 if (!(status & (se->irq_mask | se->err_mask)))
1096 return IRQ_NONE;
1097
1098#ifdef CONFIG_DEBUG_FS
1099 if (status & se->err_mask)
1100 malidp_error(malidp, &malidp->se_errors, status,
1101 drm_crtc_vblank_count(&malidp->crtc));
1102#endif
1103 mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1104 status &= mask;
1105
1106 if (status & se->vsync_irq) {
1107 switch (hwdev->mw_state) {
1108 case MW_ONESHOT:
1109 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1110 break;
1111 case MW_STOP:
1112 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1113
1114 hwdev->mw_state = MW_NOT_ENABLED;
1115 break;
1116 case MW_RESTART:
1117 drm_writeback_signal_completion(&malidp->mw_connector, 0);
1118
1119 case MW_START:
1120
1121 hw->disable_memwrite(hwdev);
1122
1123
1124
1125
1126
1127 status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1128 if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1129 (status & hw->map.dc_irq_map.vsync_irq))
1130 hw->set_config_valid(hwdev, 1);
1131 break;
1132 }
1133 }
1134
1135 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1136
1137 return IRQ_HANDLED;
1138}
1139
1140void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1141{
1142
1143 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1144 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1145
1146 malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1147 hwdev->hw->map.se_irq_map.irq_mask);
1148}
1149
1150static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1151{
1152 return IRQ_HANDLED;
1153}
1154
1155int malidp_se_irq_init(struct drm_device *drm, int irq)
1156{
1157 struct malidp_drm *malidp = drm->dev_private;
1158 struct malidp_hw_device *hwdev = malidp->dev;
1159 int ret;
1160
1161
1162 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1163 malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1164
1165 ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1166 malidp_se_irq_thread_handler,
1167 IRQF_SHARED, "malidp-se", drm);
1168 if (ret < 0) {
1169 DRM_ERROR("failed to install SE IRQ handler\n");
1170 return ret;
1171 }
1172
1173 hwdev->mw_state = MW_NOT_ENABLED;
1174 malidp_se_irq_hw_init(hwdev);
1175
1176 return 0;
1177}
1178
1179void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1180{
1181 malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1182 hwdev->hw->map.se_irq_map.irq_mask);
1183}
1184