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