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