]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/arm/malidp_hw.c
ARC: uaccess: enable INLINE_COPY_{TO,FROM}_USER ...
[karo-tx-linux.git] / drivers / gpu / drm / arm / malidp_hw.c
1 /*
2  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
3  * Author: Liviu Dudau <Liviu.Dudau@arm.com>
4  *
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
8  * of such GNU licence.
9  *
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
13  */
14
15 #include <linux/types.h>
16 #include <linux/io.h>
17 #include <drm/drmP.h>
18 #include <video/videomode.h>
19 #include <video/display_timing.h>
20
21 #include "malidp_drv.h"
22 #include "malidp_hw.h"
23
24 static const struct malidp_format_id malidp500_de_formats[] = {
25         /*    fourcc,   layers supporting the format,     internal id  */
26         { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  0 },
27         { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  1 },
28         { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  2 },
29         { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  3 },
30         { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  4 },
31         { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  5 },
32         { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  6 },
33         { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  7 },
34         { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  8 },
35         { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  9 },
36         { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
37         { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
38         { DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
39         { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
40         { DRM_FORMAT_NV12, DE_VIDEO1, 14 },
41         { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
42 };
43
44 #define MALIDP_ID(__group, __format) \
45         ((((__group) & 0x7) << 3) | ((__format) & 0x7))
46
47 #define MALIDP_COMMON_FORMATS \
48         /*    fourcc,   layers supporting the format,      internal id   */ \
49         { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(0, 0) }, \
50         { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(0, 1) }, \
51         { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(0, 2) }, \
52         { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(0, 3) }, \
53         { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
54         { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
55         { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
56         { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
57         { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(2, 0) }, \
58         { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(2, 1) }, \
59         { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(2, 2) }, \
60         { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(2, 3) }, \
61         { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(3, 0) }, \
62         { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(3, 1) }, \
63         { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
64         { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
65         { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
66         { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
67         { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) },    \
68         { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) },    \
69         { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) },    \
70         { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }
71
72 static const struct malidp_format_id malidp550_de_formats[] = {
73         MALIDP_COMMON_FORMATS,
74 };
75
76 static const struct malidp_layer malidp500_layers[] = {
77         { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
78         { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE },
79         { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE },
80 };
81
82 static const struct malidp_layer malidp550_layers[] = {
83         { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
84         { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE },
85         { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
86         { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 0 },
87 };
88
89 #define MALIDP_DE_DEFAULT_PREFETCH_START        5
90
91 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
92 {
93         u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
94         /* bit 4 of the CONFIG_ID register holds the line size multiplier */
95         u8 ln_size_mult = conf & 0x10 ? 2 : 1;
96
97         hwdev->min_line_size = 2;
98         hwdev->max_line_size = SZ_2K * ln_size_mult;
99         hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
100         hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
101
102         return 0;
103 }
104
105 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
106 {
107         u32 status, count = 100;
108
109         malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
110         while (count) {
111                 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
112                 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
113                         break;
114                 /*
115                  * entering config mode can take as long as the rendering
116                  * of a full frame, hence the long sleep here
117                  */
118                 usleep_range(1000, 10000);
119                 count--;
120         }
121         WARN(count == 0, "timeout while entering config mode");
122 }
123
124 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
125 {
126         u32 status, count = 100;
127
128         malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
129         malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
130         while (count) {
131                 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
132                 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
133                         break;
134                 usleep_range(100, 1000);
135                 count--;
136         }
137         WARN(count == 0, "timeout while leaving config mode");
138 }
139
140 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
141 {
142         u32 status;
143
144         status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
145         if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
146                 return true;
147
148         return false;
149 }
150
151 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev)
152 {
153         malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
154 }
155
156 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
157 {
158         u32 val = 0;
159
160         malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
161         if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
162                 val |= MALIDP500_HSYNCPOL;
163         if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
164                 val |= MALIDP500_VSYNCPOL;
165         val |= MALIDP_DE_DEFAULT_PREFETCH_START;
166         malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
167
168         /*
169          * Mali-DP500 encodes the background color like this:
170          *    - red   @ MALIDP500_BGND_COLOR[12:0]
171          *    - green @ MALIDP500_BGND_COLOR[27:16]
172          *    - blue  @ (MALIDP500_BGND_COLOR + 4)[12:0]
173          */
174         val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
175               (MALIDP_BGND_COLOR_R & 0xfff);
176         malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
177         malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
178
179         val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
180                 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
181         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
182
183         val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
184                 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
185         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
186
187         val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
188                 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
189         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
190
191         val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
192         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
193
194         if (mode->flags & DISPLAY_FLAGS_INTERLACED)
195                 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
196         else
197                 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
198 }
199
200 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
201 {
202         /* RGB888 or BGR888 can't be rotated */
203         if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
204                 return -EINVAL;
205
206         /*
207          * Each layer needs enough rotation memory to fit 8 lines
208          * worth of pixel data. Required size is then:
209          *    size = rotated_width * (bpp / 8) * 8;
210          */
211         return w * drm_format_plane_cpp(fmt, 0) * 8;
212 }
213
214 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
215 {
216         u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
217         u8 ln_size = (conf >> 4) & 0x3, rsize;
218
219         hwdev->min_line_size = 2;
220
221         switch (ln_size) {
222         case 0:
223                 hwdev->max_line_size = SZ_2K;
224                 /* two banks of 64KB for rotation memory */
225                 rsize = 64;
226                 break;
227         case 1:
228                 hwdev->max_line_size = SZ_4K;
229                 /* two banks of 128KB for rotation memory */
230                 rsize = 128;
231                 break;
232         case 2:
233                 hwdev->max_line_size = 1280;
234                 /* two banks of 40KB for rotation memory */
235                 rsize = 40;
236                 break;
237         case 3:
238                 /* reserved value */
239                 hwdev->max_line_size = 0;
240                 return -EINVAL;
241         }
242
243         hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
244         return 0;
245 }
246
247 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
248 {
249         u32 status, count = 100;
250
251         malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
252         while (count) {
253                 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
254                 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
255                         break;
256                 /*
257                  * entering config mode can take as long as the rendering
258                  * of a full frame, hence the long sleep here
259                  */
260                 usleep_range(1000, 10000);
261                 count--;
262         }
263         WARN(count == 0, "timeout while entering config mode");
264 }
265
266 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
267 {
268         u32 status, count = 100;
269
270         malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
271         malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
272         while (count) {
273                 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
274                 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
275                         break;
276                 usleep_range(100, 1000);
277                 count--;
278         }
279         WARN(count == 0, "timeout while leaving config mode");
280 }
281
282 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
283 {
284         u32 status;
285
286         status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
287         if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
288                 return true;
289
290         return false;
291 }
292
293 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev)
294 {
295         malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
296 }
297
298 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
299 {
300         u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
301
302         malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
303         /*
304          * Mali-DP550 and Mali-DP650 encode the background color like this:
305          *   - red   @ MALIDP550_DE_BGND_COLOR[23:16]
306          *   - green @ MALIDP550_DE_BGND_COLOR[15:8]
307          *   - blue  @ MALIDP550_DE_BGND_COLOR[7:0]
308          *
309          * We need to truncate the least significant 4 bits from the default
310          * MALIDP_BGND_COLOR_x values
311          */
312         val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
313               (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
314               ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
315         malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
316
317         val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
318                 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
319         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
320
321         val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
322                 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
323         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
324
325         val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
326                 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
327         if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
328                 val |= MALIDP550_HSYNCPOL;
329         if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
330                 val |= MALIDP550_VSYNCPOL;
331         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
332
333         val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
334         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
335
336         if (mode->flags & DISPLAY_FLAGS_INTERLACED)
337                 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
338         else
339                 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
340 }
341
342 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
343 {
344         u32 bytes_per_col;
345
346         /* raw RGB888 or BGR888 can't be rotated */
347         if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
348                 return -EINVAL;
349
350         switch (fmt) {
351         /* 8 lines at 4 bytes per pixel */
352         case DRM_FORMAT_ARGB2101010:
353         case DRM_FORMAT_ABGR2101010:
354         case DRM_FORMAT_RGBA1010102:
355         case DRM_FORMAT_BGRA1010102:
356         case DRM_FORMAT_ARGB8888:
357         case DRM_FORMAT_ABGR8888:
358         case DRM_FORMAT_RGBA8888:
359         case DRM_FORMAT_BGRA8888:
360         case DRM_FORMAT_XRGB8888:
361         case DRM_FORMAT_XBGR8888:
362         case DRM_FORMAT_RGBX8888:
363         case DRM_FORMAT_BGRX8888:
364         case DRM_FORMAT_RGB888:
365         case DRM_FORMAT_BGR888:
366         /* 16 lines at 2 bytes per pixel */
367         case DRM_FORMAT_RGBA5551:
368         case DRM_FORMAT_ABGR1555:
369         case DRM_FORMAT_RGB565:
370         case DRM_FORMAT_BGR565:
371         case DRM_FORMAT_UYVY:
372         case DRM_FORMAT_YUYV:
373                 bytes_per_col = 32;
374                 break;
375         /* 16 lines at 1.5 bytes per pixel */
376         case DRM_FORMAT_NV12:
377         case DRM_FORMAT_YUV420:
378                 bytes_per_col = 24;
379                 break;
380         default:
381                 return -EINVAL;
382         }
383
384         return w * bytes_per_col;
385 }
386
387 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
388 {
389         u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
390         u8 ln_size = (conf >> 4) & 0x3, rsize;
391
392         hwdev->min_line_size = 4;
393
394         switch (ln_size) {
395         case 0:
396         case 2:
397                 /* reserved values */
398                 hwdev->max_line_size = 0;
399                 return -EINVAL;
400         case 1:
401                 hwdev->max_line_size = SZ_4K;
402                 /* two banks of 128KB for rotation memory */
403                 rsize = 128;
404                 break;
405         case 3:
406                 hwdev->max_line_size = 2560;
407                 /* two banks of 80KB for rotation memory */
408                 rsize = 80;
409         }
410
411         hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
412         return 0;
413 }
414
415 const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
416         [MALIDP_500] = {
417                 .map = {
418                         .se_base = MALIDP500_SE_BASE,
419                         .dc_base = MALIDP500_DC_BASE,
420                         .out_depth_base = MALIDP500_OUTPUT_DEPTH,
421                         .features = 0,  /* no CLEARIRQ register */
422                         .n_layers = ARRAY_SIZE(malidp500_layers),
423                         .layers = malidp500_layers,
424                         .de_irq_map = {
425                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
426                                             MALIDP500_DE_IRQ_AXI_ERR |
427                                             MALIDP500_DE_IRQ_VSYNC |
428                                             MALIDP500_DE_IRQ_GLOBAL,
429                                 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
430                         },
431                         .se_irq_map = {
432                                 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE,
433                                 .vsync_irq = 0,
434                         },
435                         .dc_irq_map = {
436                                 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
437                                 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
438                         },
439                         .pixel_formats = malidp500_de_formats,
440                         .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
441                         .bus_align_bytes = 8,
442                 },
443                 .query_hw = malidp500_query_hw,
444                 .enter_config_mode = malidp500_enter_config_mode,
445                 .leave_config_mode = malidp500_leave_config_mode,
446                 .in_config_mode = malidp500_in_config_mode,
447                 .set_config_valid = malidp500_set_config_valid,
448                 .modeset = malidp500_modeset,
449                 .rotmem_required = malidp500_rotmem_required,
450                 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
451         },
452         [MALIDP_550] = {
453                 .map = {
454                         .se_base = MALIDP550_SE_BASE,
455                         .dc_base = MALIDP550_DC_BASE,
456                         .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
457                         .features = MALIDP_REGMAP_HAS_CLEARIRQ,
458                         .n_layers = ARRAY_SIZE(malidp550_layers),
459                         .layers = malidp550_layers,
460                         .de_irq_map = {
461                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
462                                             MALIDP550_DE_IRQ_VSYNC,
463                                 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
464                         },
465                         .se_irq_map = {
466                                 .irq_mask = MALIDP550_SE_IRQ_EOW |
467                                             MALIDP550_SE_IRQ_AXI_ERR,
468                         },
469                         .dc_irq_map = {
470                                 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID,
471                                 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
472                         },
473                         .pixel_formats = malidp550_de_formats,
474                         .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
475                         .bus_align_bytes = 8,
476                 },
477                 .query_hw = malidp550_query_hw,
478                 .enter_config_mode = malidp550_enter_config_mode,
479                 .leave_config_mode = malidp550_leave_config_mode,
480                 .in_config_mode = malidp550_in_config_mode,
481                 .set_config_valid = malidp550_set_config_valid,
482                 .modeset = malidp550_modeset,
483                 .rotmem_required = malidp550_rotmem_required,
484                 .features = 0,
485         },
486         [MALIDP_650] = {
487                 .map = {
488                         .se_base = MALIDP550_SE_BASE,
489                         .dc_base = MALIDP550_DC_BASE,
490                         .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
491                         .features = MALIDP_REGMAP_HAS_CLEARIRQ,
492                         .n_layers = ARRAY_SIZE(malidp550_layers),
493                         .layers = malidp550_layers,
494                         .de_irq_map = {
495                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
496                                             MALIDP650_DE_IRQ_DRIFT |
497                                             MALIDP550_DE_IRQ_VSYNC,
498                                 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
499                         },
500                         .se_irq_map = {
501                                 .irq_mask = MALIDP550_SE_IRQ_EOW |
502                                             MALIDP550_SE_IRQ_AXI_ERR,
503                         },
504                         .dc_irq_map = {
505                                 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID,
506                                 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
507                         },
508                         .pixel_formats = malidp550_de_formats,
509                         .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
510                         .bus_align_bytes = 16,
511                 },
512                 .query_hw = malidp650_query_hw,
513                 .enter_config_mode = malidp550_enter_config_mode,
514                 .leave_config_mode = malidp550_leave_config_mode,
515                 .in_config_mode = malidp550_in_config_mode,
516                 .set_config_valid = malidp550_set_config_valid,
517                 .modeset = malidp550_modeset,
518                 .rotmem_required = malidp550_rotmem_required,
519                 .features = 0,
520         },
521 };
522
523 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
524                            u8 layer_id, u32 format)
525 {
526         unsigned int i;
527
528         for (i = 0; i < map->n_pixel_formats; i++) {
529                 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
530                     (map->pixel_formats[i].format == format))
531                         return map->pixel_formats[i].id;
532         }
533
534         return MALIDP_INVALID_FORMAT_ID;
535 }
536
537 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
538 {
539         u32 base = malidp_get_block_base(hwdev, block);
540
541         if (hwdev->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
542                 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
543         else
544                 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
545 }
546
547 static irqreturn_t malidp_de_irq(int irq, void *arg)
548 {
549         struct drm_device *drm = arg;
550         struct malidp_drm *malidp = drm->dev_private;
551         struct malidp_hw_device *hwdev;
552         const struct malidp_irq_map *de;
553         u32 status, mask, dc_status;
554         irqreturn_t ret = IRQ_NONE;
555
556         if (!drm->dev_private)
557                 return IRQ_HANDLED;
558
559         hwdev = malidp->dev;
560         de = &hwdev->map.de_irq_map;
561
562         /* first handle the config valid IRQ */
563         dc_status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
564         if (dc_status & hwdev->map.dc_irq_map.vsync_irq) {
565                 /* we have a page flip event */
566                 atomic_set(&malidp->config_valid, 1);
567                 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
568                 ret = IRQ_WAKE_THREAD;
569         }
570
571         status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
572         if (!(status & de->irq_mask))
573                 return ret;
574
575         mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
576         status &= mask;
577         if (status & de->vsync_irq)
578                 drm_crtc_handle_vblank(&malidp->crtc);
579
580         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
581
582         return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
583 }
584
585 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
586 {
587         struct drm_device *drm = arg;
588         struct malidp_drm *malidp = drm->dev_private;
589
590         wake_up(&malidp->wq);
591
592         return IRQ_HANDLED;
593 }
594
595 int malidp_de_irq_init(struct drm_device *drm, int irq)
596 {
597         struct malidp_drm *malidp = drm->dev_private;
598         struct malidp_hw_device *hwdev = malidp->dev;
599         int ret;
600
601         /* ensure interrupts are disabled */
602         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
603         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
604         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
605         malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
606
607         ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
608                                         malidp_de_irq_thread_handler,
609                                         IRQF_SHARED, "malidp-de", drm);
610         if (ret < 0) {
611                 DRM_ERROR("failed to install DE IRQ handler\n");
612                 return ret;
613         }
614
615         /* first enable the DC block IRQs */
616         malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
617                              hwdev->map.dc_irq_map.irq_mask);
618
619         /* now enable the DE block IRQs */
620         malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
621                              hwdev->map.de_irq_map.irq_mask);
622
623         return 0;
624 }
625
626 void malidp_de_irq_fini(struct drm_device *drm)
627 {
628         struct malidp_drm *malidp = drm->dev_private;
629         struct malidp_hw_device *hwdev = malidp->dev;
630
631         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
632                               hwdev->map.de_irq_map.irq_mask);
633         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
634                               hwdev->map.dc_irq_map.irq_mask);
635 }
636
637 static irqreturn_t malidp_se_irq(int irq, void *arg)
638 {
639         struct drm_device *drm = arg;
640         struct malidp_drm *malidp = drm->dev_private;
641         struct malidp_hw_device *hwdev = malidp->dev;
642         u32 status, mask;
643
644         status = malidp_hw_read(hwdev, hwdev->map.se_base + MALIDP_REG_STATUS);
645         if (!(status & hwdev->map.se_irq_map.irq_mask))
646                 return IRQ_NONE;
647
648         mask = malidp_hw_read(hwdev, hwdev->map.se_base + MALIDP_REG_MASKIRQ);
649         status = malidp_hw_read(hwdev, hwdev->map.se_base + MALIDP_REG_STATUS);
650         status &= mask;
651         /* ToDo: status decoding and firing up of VSYNC and page flip events */
652
653         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
654
655         return IRQ_HANDLED;
656 }
657
658 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
659 {
660         return IRQ_HANDLED;
661 }
662
663 int malidp_se_irq_init(struct drm_device *drm, int irq)
664 {
665         struct malidp_drm *malidp = drm->dev_private;
666         struct malidp_hw_device *hwdev = malidp->dev;
667         int ret;
668
669         /* ensure interrupts are disabled */
670         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
671         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
672
673         ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
674                                         malidp_se_irq_thread_handler,
675                                         IRQF_SHARED, "malidp-se", drm);
676         if (ret < 0) {
677                 DRM_ERROR("failed to install SE IRQ handler\n");
678                 return ret;
679         }
680
681         malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
682                              hwdev->map.se_irq_map.irq_mask);
683
684         return 0;
685 }
686
687 void malidp_se_irq_fini(struct drm_device *drm)
688 {
689         struct malidp_drm *malidp = drm->dev_private;
690         struct malidp_hw_device *hwdev = malidp->dev;
691
692         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
693                               hwdev->map.se_irq_map.irq_mask);
694 }