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