]> Git Repo - linux.git/blob - drivers/gpu/drm/arm/malidp_hw.c
Merge branch 'for-5.0' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[linux.git] / drivers / gpu / drm / arm / malidp_hw.c
1 /*
2  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
3  * Author: Liviu Dudau <[email protected]>
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         { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}
82
83 static const struct malidp_format_id malidp550_de_formats[] = {
84         MALIDP_COMMON_FORMATS,
85 };
86
87 static 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
92 static const struct malidp_layer malidp500_layers[] = {
93         /* id, base address, fb pointer address base, stride offset,
94          *      yuv2rgb matrix offset, mmu control register offset, rotation_features
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
104 static const struct malidp_layer malidp550_layers[] = {
105         /* id, base address, fb pointer address base, stride offset,
106          *      yuv2rgb matrix offset, mmu control register offset, rotation_features
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
118 static const struct malidp_layer malidp650_layers[] = {
119         /* id, base address, fb pointer address base, stride offset,
120          *      yuv2rgb matrix offset, mmu control register offset,
121          *      rotation_features
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
138 static 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
213 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
214 {
215         u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
216         /* bit 4 of the CONFIG_ID register holds the line size multiplier */
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; /* no second rotation memory bank */
223
224         return 0;
225 }
226
227 static 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                  * entering config mode can take as long as the rendering
238                  * of a full frame, hence the long sleep here
239                  */
240                 usleep_range(1000, 10000);
241                 count--;
242         }
243         WARN(count == 0, "timeout while entering config mode");
244 }
245
246 static 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
262 static 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
273 static 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
281 static 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          * Mali-DP500 encodes the background color like this:
297          *    - red   @ MALIDP500_BGND_COLOR[12:0]
298          *    - green @ MALIDP500_BGND_COLOR[27:16]
299          *    - blue  @ (MALIDP500_BGND_COLOR + 4)[12:0]
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
327 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
328 {
329         /*
330          * Each layer needs enough rotation memory to fit 8 lines
331          * worth of pixel data. Required size is then:
332          *    size = rotated_width * (bpp / 8) * 8;
333          */
334         return w * drm_format_plane_cpp(fmt, 0) * 8;
335 }
336
337 static 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
354 static 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         /* Get array indices into dp500_se_scaling_coeffs. */
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
386 static 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; /* Hz */
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          * mclk = max(a, 1.5) * pxlclk
400          *
401          * To avoid float calculaiton, using 15 instead of 1.5 and div by
402          * 10 to get mclk.
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
419 static 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         /* enable the scaling engine block */
428         malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
429
430         /* restart the writeback if already enabled */
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                 /* fall through */
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
469 static 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
479 static 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                 /* two banks of 64KB for rotation memory */
490                 rsize = 64;
491                 break;
492         case 1:
493                 hwdev->max_line_size = SZ_4K;
494                 /* two banks of 128KB for rotation memory */
495                 rsize = 128;
496                 break;
497         case 2:
498                 hwdev->max_line_size = 1280;
499                 /* two banks of 40KB for rotation memory */
500                 rsize = 40;
501                 break;
502         case 3:
503                 /* reserved value */
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
512 static 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                  * entering config mode can take as long as the rendering
523                  * of a full frame, hence the long sleep here
524                  */
525                 usleep_range(1000, 10000);
526                 count--;
527         }
528         WARN(count == 0, "timeout while entering config mode");
529 }
530
531 static 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
547 static 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
558 static 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
566 static 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          * Mali-DP550 and Mali-DP650 encode the background color like this:
575          *   - red   @ MALIDP550_DE_BGND_COLOR[23:16]
576          *   - green @ MALIDP550_DE_BGND_COLOR[15:8]
577          *   - blue  @ MALIDP550_DE_BGND_COLOR[7:0]
578          *
579          * We need to truncate the least significant 4 bits from the default
580          * MALIDP_BGND_COLOR_x values
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
612 static 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         /* 8 lines at 4 bytes per pixel */
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         /* 16 lines at 2 bytes per pixel */
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         /* 16 lines at 1.5 bytes per pixel */
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
655 static 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
669 static 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         /* mclk can't be slower than pxlclk. */
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
702 static 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         /* enable the scaling engine block */
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                 /* fall through */
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
748 static 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
757 static 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                 /* reserved values */
768                 hwdev->max_line_size = 0;
769                 return -EINVAL;
770         case 1:
771                 hwdev->max_line_size = SZ_4K;
772                 /* two banks of 128KB for rotation memory */
773                 rsize = 128;
774                 break;
775         case 3:
776                 hwdev->max_line_size = 2560;
777                 /* two banks of 80KB for rotation memory */
778                 rsize = 80;
779         }
780
781         hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
782         return 0;
783 }
784
785 const 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,  /* no CLEARIRQ register */
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
935 u8 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
949 static 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
959 static 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          * if we are suspended it is likely that we were invoked because
975          * we share an interrupt line with some other driver, don't try
976          * to read the hardware registers
977          */
978         if (hwdev->pm_suspended)
979                 return IRQ_NONE;
980
981         /* first handle the config valid IRQ */
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                 /* do we have a page flip event? */
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         /* keep the status of the enabled interrupts, plus the error bits */
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
1017 static 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
1027 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1028 {
1029         /* ensure interrupts are disabled */
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         /* first enable the DC block IRQs */
1036         malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1037                              hwdev->hw->map.dc_irq_map.irq_mask);
1038
1039         /* now enable the DE block IRQs */
1040         malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1041                              hwdev->hw->map.de_irq_map.irq_mask);
1042 }
1043
1044 int 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         /* ensure interrupts are disabled */
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
1069 void 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
1077 static 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          * if we are suspended it is likely that we were invoked because
1088          * we share an interrupt line with some other driver, don't try
1089          * to read the hardware registers
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                         /* disable writeback after stop */
1114                         hwdev->mw_state = MW_NOT_ENABLED;
1115                         break;
1116                 case MW_RESTART:
1117                         drm_writeback_signal_completion(&malidp->mw_connector, 0);
1118                         /* fall through to a new start */
1119                 case MW_START:
1120                         /* writeback started, need to emulate one-shot mode */
1121                         hw->disable_memwrite(hwdev);
1122                         /*
1123                          * only set config_valid HW bit if there is no other update
1124                          * in progress or if we raced ahead of the DE IRQ handler
1125                          * and config_valid flag will not be update until later
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
1140 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1141 {
1142         /* ensure interrupts are disabled */
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
1150 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1151 {
1152         return IRQ_HANDLED;
1153 }
1154
1155 int 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         /* ensure interrupts are disabled */
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
1179 void 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 }
This page took 0.106655 seconds and 4 git commands to generate.