1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
3  */
4 
5 #include <linux/bitops.h>
6 #include <linux/slab.h>
7 
8 #include "dpu_kms.h"
9 #include "dpu_hw_interrupts.h"
10 #include "dpu_hw_util.h"
11 #include "dpu_hw_mdss.h"
12 
13 /**
14  * Register offsets in MDSS register file for the interrupt registers
15  * w.r.t. to the MDP base
16  */
17 #define MDP_SSPP_TOP0_OFF		0x0
18 #define MDP_INTF_0_OFF			0x6A000
19 #define MDP_INTF_1_OFF			0x6A800
20 #define MDP_INTF_2_OFF			0x6B000
21 #define MDP_INTF_3_OFF			0x6B800
22 #define MDP_INTF_4_OFF			0x6C000
23 #define MDP_AD4_0_OFF			0x7C000
24 #define MDP_AD4_1_OFF			0x7D000
25 #define MDP_AD4_INTR_EN_OFF		0x41c
26 #define MDP_AD4_INTR_CLEAR_OFF		0x424
27 #define MDP_AD4_INTR_STATUS_OFF		0x420
28 
29 /**
30  * WB interrupt status bit definitions
31  */
32 #define DPU_INTR_WB_0_DONE BIT(0)
33 #define DPU_INTR_WB_1_DONE BIT(1)
34 #define DPU_INTR_WB_2_DONE BIT(4)
35 
36 /**
37  * WDOG timer interrupt status bit definitions
38  */
39 #define DPU_INTR_WD_TIMER_0_DONE BIT(2)
40 #define DPU_INTR_WD_TIMER_1_DONE BIT(3)
41 #define DPU_INTR_WD_TIMER_2_DONE BIT(5)
42 #define DPU_INTR_WD_TIMER_3_DONE BIT(6)
43 #define DPU_INTR_WD_TIMER_4_DONE BIT(7)
44 
45 /**
46  * Pingpong interrupt status bit definitions
47  */
48 #define DPU_INTR_PING_PONG_0_DONE BIT(8)
49 #define DPU_INTR_PING_PONG_1_DONE BIT(9)
50 #define DPU_INTR_PING_PONG_2_DONE BIT(10)
51 #define DPU_INTR_PING_PONG_3_DONE BIT(11)
52 #define DPU_INTR_PING_PONG_0_RD_PTR BIT(12)
53 #define DPU_INTR_PING_PONG_1_RD_PTR BIT(13)
54 #define DPU_INTR_PING_PONG_2_RD_PTR BIT(14)
55 #define DPU_INTR_PING_PONG_3_RD_PTR BIT(15)
56 #define DPU_INTR_PING_PONG_0_WR_PTR BIT(16)
57 #define DPU_INTR_PING_PONG_1_WR_PTR BIT(17)
58 #define DPU_INTR_PING_PONG_2_WR_PTR BIT(18)
59 #define DPU_INTR_PING_PONG_3_WR_PTR BIT(19)
60 #define DPU_INTR_PING_PONG_0_AUTOREFRESH_DONE BIT(20)
61 #define DPU_INTR_PING_PONG_1_AUTOREFRESH_DONE BIT(21)
62 #define DPU_INTR_PING_PONG_2_AUTOREFRESH_DONE BIT(22)
63 #define DPU_INTR_PING_PONG_3_AUTOREFRESH_DONE BIT(23)
64 
65 /**
66  * Interface interrupt status bit definitions
67  */
68 #define DPU_INTR_INTF_0_UNDERRUN BIT(24)
69 #define DPU_INTR_INTF_1_UNDERRUN BIT(26)
70 #define DPU_INTR_INTF_2_UNDERRUN BIT(28)
71 #define DPU_INTR_INTF_3_UNDERRUN BIT(30)
72 #define DPU_INTR_INTF_0_VSYNC BIT(25)
73 #define DPU_INTR_INTF_1_VSYNC BIT(27)
74 #define DPU_INTR_INTF_2_VSYNC BIT(29)
75 #define DPU_INTR_INTF_3_VSYNC BIT(31)
76 
77 /**
78  * Pingpong Secondary interrupt status bit definitions
79  */
80 #define DPU_INTR_PING_PONG_S0_AUTOREFRESH_DONE BIT(0)
81 #define DPU_INTR_PING_PONG_S0_WR_PTR BIT(4)
82 #define DPU_INTR_PING_PONG_S0_RD_PTR BIT(8)
83 #define DPU_INTR_PING_PONG_S0_TEAR_DETECTED BIT(22)
84 #define DPU_INTR_PING_PONG_S0_TE_DETECTED BIT(28)
85 
86 /**
87  * Pingpong TEAR detection interrupt status bit definitions
88  */
89 #define DPU_INTR_PING_PONG_0_TEAR_DETECTED BIT(16)
90 #define DPU_INTR_PING_PONG_1_TEAR_DETECTED BIT(17)
91 #define DPU_INTR_PING_PONG_2_TEAR_DETECTED BIT(18)
92 #define DPU_INTR_PING_PONG_3_TEAR_DETECTED BIT(19)
93 
94 /**
95  * Pingpong TE detection interrupt status bit definitions
96  */
97 #define DPU_INTR_PING_PONG_0_TE_DETECTED BIT(24)
98 #define DPU_INTR_PING_PONG_1_TE_DETECTED BIT(25)
99 #define DPU_INTR_PING_PONG_2_TE_DETECTED BIT(26)
100 #define DPU_INTR_PING_PONG_3_TE_DETECTED BIT(27)
101 
102 /**
103  * Ctl start interrupt status bit definitions
104  */
105 #define DPU_INTR_CTL_0_START BIT(9)
106 #define DPU_INTR_CTL_1_START BIT(10)
107 #define DPU_INTR_CTL_2_START BIT(11)
108 #define DPU_INTR_CTL_3_START BIT(12)
109 #define DPU_INTR_CTL_4_START BIT(13)
110 
111 /**
112  * Concurrent WB overflow interrupt status bit definitions
113  */
114 #define DPU_INTR_CWB_2_OVERFLOW BIT(14)
115 #define DPU_INTR_CWB_3_OVERFLOW BIT(15)
116 
117 /**
118  * Histogram VIG done interrupt status bit definitions
119  */
120 #define DPU_INTR_HIST_VIG_0_DONE BIT(0)
121 #define DPU_INTR_HIST_VIG_1_DONE BIT(4)
122 #define DPU_INTR_HIST_VIG_2_DONE BIT(8)
123 #define DPU_INTR_HIST_VIG_3_DONE BIT(10)
124 
125 /**
126  * Histogram VIG reset Sequence done interrupt status bit definitions
127  */
128 #define DPU_INTR_HIST_VIG_0_RSTSEQ_DONE BIT(1)
129 #define DPU_INTR_HIST_VIG_1_RSTSEQ_DONE BIT(5)
130 #define DPU_INTR_HIST_VIG_2_RSTSEQ_DONE BIT(9)
131 #define DPU_INTR_HIST_VIG_3_RSTSEQ_DONE BIT(11)
132 
133 /**
134  * Histogram DSPP done interrupt status bit definitions
135  */
136 #define DPU_INTR_HIST_DSPP_0_DONE BIT(12)
137 #define DPU_INTR_HIST_DSPP_1_DONE BIT(16)
138 #define DPU_INTR_HIST_DSPP_2_DONE BIT(20)
139 #define DPU_INTR_HIST_DSPP_3_DONE BIT(22)
140 
141 /**
142  * Histogram DSPP reset Sequence done interrupt status bit definitions
143  */
144 #define DPU_INTR_HIST_DSPP_0_RSTSEQ_DONE BIT(13)
145 #define DPU_INTR_HIST_DSPP_1_RSTSEQ_DONE BIT(17)
146 #define DPU_INTR_HIST_DSPP_2_RSTSEQ_DONE BIT(21)
147 #define DPU_INTR_HIST_DSPP_3_RSTSEQ_DONE BIT(23)
148 
149 /**
150  * INTF interrupt status bit definitions
151  */
152 #define DPU_INTR_VIDEO_INTO_STATIC BIT(0)
153 #define DPU_INTR_VIDEO_OUTOF_STATIC BIT(1)
154 #define DPU_INTR_DSICMD_0_INTO_STATIC BIT(2)
155 #define DPU_INTR_DSICMD_0_OUTOF_STATIC BIT(3)
156 #define DPU_INTR_DSICMD_1_INTO_STATIC BIT(4)
157 #define DPU_INTR_DSICMD_1_OUTOF_STATIC BIT(5)
158 #define DPU_INTR_DSICMD_2_INTO_STATIC BIT(6)
159 #define DPU_INTR_DSICMD_2_OUTOF_STATIC BIT(7)
160 #define DPU_INTR_PROG_LINE BIT(8)
161 
162 /**
163  * AD4 interrupt status bit definitions
164  */
165 #define DPU_INTR_BACKLIGHT_UPDATED BIT(0)
166 /**
167  * struct dpu_intr_reg - array of DPU register sets
168  * @clr_off:	offset to CLEAR reg
169  * @en_off:	offset to ENABLE reg
170  * @status_off:	offset to STATUS reg
171  */
172 struct dpu_intr_reg {
173 	u32 clr_off;
174 	u32 en_off;
175 	u32 status_off;
176 };
177 
178 /**
179  * struct dpu_irq_type - maps each irq with i/f
180  * @intr_type:		type of interrupt listed in dpu_intr_type
181  * @instance_idx:	instance index of the associated HW block in DPU
182  * @irq_mask:		corresponding bit in the interrupt status reg
183  * @reg_idx:		which reg set to use
184  */
185 struct dpu_irq_type {
186 	u32 intr_type;
187 	u32 instance_idx;
188 	u32 irq_mask;
189 	u32 reg_idx;
190 };
191 
192 /**
193  * List of DPU interrupt registers
194  */
195 static const struct dpu_intr_reg dpu_intr_set[] = {
196 	{
197 		MDP_SSPP_TOP0_OFF+INTR_CLEAR,
198 		MDP_SSPP_TOP0_OFF+INTR_EN,
199 		MDP_SSPP_TOP0_OFF+INTR_STATUS
200 	},
201 	{
202 		MDP_SSPP_TOP0_OFF+INTR2_CLEAR,
203 		MDP_SSPP_TOP0_OFF+INTR2_EN,
204 		MDP_SSPP_TOP0_OFF+INTR2_STATUS
205 	},
206 	{
207 		MDP_SSPP_TOP0_OFF+HIST_INTR_CLEAR,
208 		MDP_SSPP_TOP0_OFF+HIST_INTR_EN,
209 		MDP_SSPP_TOP0_OFF+HIST_INTR_STATUS
210 	},
211 	{
212 		MDP_INTF_0_OFF+INTF_INTR_CLEAR,
213 		MDP_INTF_0_OFF+INTF_INTR_EN,
214 		MDP_INTF_0_OFF+INTF_INTR_STATUS
215 	},
216 	{
217 		MDP_INTF_1_OFF+INTF_INTR_CLEAR,
218 		MDP_INTF_1_OFF+INTF_INTR_EN,
219 		MDP_INTF_1_OFF+INTF_INTR_STATUS
220 	},
221 	{
222 		MDP_INTF_2_OFF+INTF_INTR_CLEAR,
223 		MDP_INTF_2_OFF+INTF_INTR_EN,
224 		MDP_INTF_2_OFF+INTF_INTR_STATUS
225 	},
226 	{
227 		MDP_INTF_3_OFF+INTF_INTR_CLEAR,
228 		MDP_INTF_3_OFF+INTF_INTR_EN,
229 		MDP_INTF_3_OFF+INTF_INTR_STATUS
230 	},
231 	{
232 		MDP_INTF_4_OFF+INTF_INTR_CLEAR,
233 		MDP_INTF_4_OFF+INTF_INTR_EN,
234 		MDP_INTF_4_OFF+INTF_INTR_STATUS
235 	},
236 	{
237 		MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF,
238 		MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF,
239 		MDP_AD4_0_OFF + MDP_AD4_INTR_STATUS_OFF,
240 	},
241 	{
242 		MDP_AD4_1_OFF + MDP_AD4_INTR_CLEAR_OFF,
243 		MDP_AD4_1_OFF + MDP_AD4_INTR_EN_OFF,
244 		MDP_AD4_1_OFF + MDP_AD4_INTR_STATUS_OFF,
245 	}
246 };
247 
248 /**
249  * IRQ mapping table - use for lookup an irq_idx in this table that have
250  *                     a matching interface type and instance index.
251  */
252 static const struct dpu_irq_type dpu_irq_map[] = {
253 	/* BEGIN MAP_RANGE: 0-31, INTR */
254 	/* irq_idx: 0-3 */
255 	{ DPU_IRQ_TYPE_WB_ROT_COMP, WB_0, DPU_INTR_WB_0_DONE, 0},
256 	{ DPU_IRQ_TYPE_WB_ROT_COMP, WB_1, DPU_INTR_WB_1_DONE, 0},
257 	{ DPU_IRQ_TYPE_WD_TIMER, WD_TIMER_0, DPU_INTR_WD_TIMER_0_DONE, 0},
258 	{ DPU_IRQ_TYPE_WD_TIMER, WD_TIMER_1, DPU_INTR_WD_TIMER_1_DONE, 0},
259 	/* irq_idx: 4-7 */
260 	{ DPU_IRQ_TYPE_WB_WFD_COMP, WB_2, DPU_INTR_WB_2_DONE, 0},
261 	{ DPU_IRQ_TYPE_WD_TIMER, WD_TIMER_2, DPU_INTR_WD_TIMER_2_DONE, 0},
262 	{ DPU_IRQ_TYPE_WD_TIMER, WD_TIMER_3, DPU_INTR_WD_TIMER_3_DONE, 0},
263 	{ DPU_IRQ_TYPE_WD_TIMER, WD_TIMER_4, DPU_INTR_WD_TIMER_4_DONE, 0},
264 	/* irq_idx: 8-11 */
265 	{ DPU_IRQ_TYPE_PING_PONG_COMP, PINGPONG_0,
266 		DPU_INTR_PING_PONG_0_DONE, 0},
267 	{ DPU_IRQ_TYPE_PING_PONG_COMP, PINGPONG_1,
268 		DPU_INTR_PING_PONG_1_DONE, 0},
269 	{ DPU_IRQ_TYPE_PING_PONG_COMP, PINGPONG_2,
270 		DPU_INTR_PING_PONG_2_DONE, 0},
271 	{ DPU_IRQ_TYPE_PING_PONG_COMP, PINGPONG_3,
272 		DPU_INTR_PING_PONG_3_DONE, 0},
273 	/* irq_idx: 12-15 */
274 	{ DPU_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_0,
275 		DPU_INTR_PING_PONG_0_RD_PTR, 0},
276 	{ DPU_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_1,
277 		DPU_INTR_PING_PONG_1_RD_PTR, 0},
278 	{ DPU_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_2,
279 		DPU_INTR_PING_PONG_2_RD_PTR, 0},
280 	{ DPU_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_3,
281 		DPU_INTR_PING_PONG_3_RD_PTR, 0},
282 	/* irq_idx: 16-19 */
283 	{ DPU_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_0,
284 		DPU_INTR_PING_PONG_0_WR_PTR, 0},
285 	{ DPU_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_1,
286 		DPU_INTR_PING_PONG_1_WR_PTR, 0},
287 	{ DPU_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_2,
288 		DPU_INTR_PING_PONG_2_WR_PTR, 0},
289 	{ DPU_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_3,
290 		DPU_INTR_PING_PONG_3_WR_PTR, 0},
291 	/* irq_idx: 20-23 */
292 	{ DPU_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_0,
293 		DPU_INTR_PING_PONG_0_AUTOREFRESH_DONE, 0},
294 	{ DPU_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_1,
295 		DPU_INTR_PING_PONG_1_AUTOREFRESH_DONE, 0},
296 	{ DPU_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_2,
297 		DPU_INTR_PING_PONG_2_AUTOREFRESH_DONE, 0},
298 	{ DPU_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_3,
299 		DPU_INTR_PING_PONG_3_AUTOREFRESH_DONE, 0},
300 	/* irq_idx: 24-27 */
301 	{ DPU_IRQ_TYPE_INTF_UNDER_RUN, INTF_0, DPU_INTR_INTF_0_UNDERRUN, 0},
302 	{ DPU_IRQ_TYPE_INTF_VSYNC, INTF_0, DPU_INTR_INTF_0_VSYNC, 0},
303 	{ DPU_IRQ_TYPE_INTF_UNDER_RUN, INTF_1, DPU_INTR_INTF_1_UNDERRUN, 0},
304 	{ DPU_IRQ_TYPE_INTF_VSYNC, INTF_1, DPU_INTR_INTF_1_VSYNC, 0},
305 	/* irq_idx: 28-31 */
306 	{ DPU_IRQ_TYPE_INTF_UNDER_RUN, INTF_2, DPU_INTR_INTF_2_UNDERRUN, 0},
307 	{ DPU_IRQ_TYPE_INTF_VSYNC, INTF_2, DPU_INTR_INTF_2_VSYNC, 0},
308 	{ DPU_IRQ_TYPE_INTF_UNDER_RUN, INTF_3, DPU_INTR_INTF_3_UNDERRUN, 0},
309 	{ DPU_IRQ_TYPE_INTF_VSYNC, INTF_3, DPU_INTR_INTF_3_VSYNC, 0},
310 
311 	/* BEGIN MAP_RANGE: 32-64, INTR2 */
312 	/* irq_idx: 32-35 */
313 	{ DPU_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_S0,
314 		DPU_INTR_PING_PONG_S0_AUTOREFRESH_DONE, 1},
315 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
316 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
317 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
318 	/* irq_idx: 36-39 */
319 	{ DPU_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_S0,
320 		DPU_INTR_PING_PONG_S0_WR_PTR, 1},
321 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
322 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
323 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
324 	/* irq_idx: 40 */
325 	{ DPU_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_S0,
326 		DPU_INTR_PING_PONG_S0_RD_PTR, 1},
327 	/* irq_idx: 41-45 */
328 	{ DPU_IRQ_TYPE_CTL_START, CTL_0,
329 		DPU_INTR_CTL_0_START, 1},
330 	{ DPU_IRQ_TYPE_CTL_START, CTL_1,
331 		DPU_INTR_CTL_1_START, 1},
332 	{ DPU_IRQ_TYPE_CTL_START, CTL_2,
333 		DPU_INTR_CTL_2_START, 1},
334 	{ DPU_IRQ_TYPE_CTL_START, CTL_3,
335 		DPU_INTR_CTL_3_START, 1},
336 	{ DPU_IRQ_TYPE_CTL_START, CTL_4,
337 		DPU_INTR_CTL_4_START, 1},
338 	/* irq_idx: 46-47 */
339 	{ DPU_IRQ_TYPE_CWB_OVERFLOW, CWB_2, DPU_INTR_CWB_2_OVERFLOW, 1},
340 	{ DPU_IRQ_TYPE_CWB_OVERFLOW, CWB_3, DPU_INTR_CWB_3_OVERFLOW, 1},
341 	/* irq_idx: 48-51 */
342 	{ DPU_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_0,
343 		DPU_INTR_PING_PONG_0_TEAR_DETECTED, 1},
344 	{ DPU_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_1,
345 		DPU_INTR_PING_PONG_1_TEAR_DETECTED, 1},
346 	{ DPU_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_2,
347 		DPU_INTR_PING_PONG_2_TEAR_DETECTED, 1},
348 	{ DPU_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_3,
349 		DPU_INTR_PING_PONG_3_TEAR_DETECTED, 1},
350 	/* irq_idx: 52-55 */
351 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
352 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
353 	{ DPU_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_S0,
354 		DPU_INTR_PING_PONG_S0_TEAR_DETECTED, 1},
355 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
356 	/* irq_idx: 56-59 */
357 	{ DPU_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_0,
358 		DPU_INTR_PING_PONG_0_TE_DETECTED, 1},
359 	{ DPU_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_1,
360 		DPU_INTR_PING_PONG_1_TE_DETECTED, 1},
361 	{ DPU_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_2,
362 		DPU_INTR_PING_PONG_2_TE_DETECTED, 1},
363 	{ DPU_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_3,
364 		DPU_INTR_PING_PONG_3_TE_DETECTED, 1},
365 	/* irq_idx: 60-63 */
366 	{ DPU_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_S0,
367 		DPU_INTR_PING_PONG_S0_TE_DETECTED, 1},
368 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
369 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
370 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 1},
371 
372 	/* BEGIN MAP_RANGE: 64-95 HIST */
373 	/* irq_idx: 64-67 */
374 	{ DPU_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG0, DPU_INTR_HIST_VIG_0_DONE, 2},
375 	{ DPU_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG0,
376 		DPU_INTR_HIST_VIG_0_RSTSEQ_DONE, 2},
377 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
378 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
379 	/* irq_idx: 68-71 */
380 	{ DPU_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG1, DPU_INTR_HIST_VIG_1_DONE, 2},
381 	{ DPU_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG1,
382 		DPU_INTR_HIST_VIG_1_RSTSEQ_DONE, 2},
383 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
384 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
385 	/* irq_idx: 72-75 */
386 	{ DPU_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG2, DPU_INTR_HIST_VIG_2_DONE, 2},
387 	{ DPU_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG2,
388 		DPU_INTR_HIST_VIG_2_RSTSEQ_DONE, 2},
389 	{ DPU_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG3, DPU_INTR_HIST_VIG_3_DONE, 2},
390 	{ DPU_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG3,
391 		DPU_INTR_HIST_VIG_3_RSTSEQ_DONE, 2},
392 	/* irq_idx: 76-79 */
393 	{ DPU_IRQ_TYPE_HIST_DSPP_DONE, DSPP_0, DPU_INTR_HIST_DSPP_0_DONE, 2},
394 	{ DPU_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_0,
395 		DPU_INTR_HIST_DSPP_0_RSTSEQ_DONE, 2},
396 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
397 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
398 	/* irq_idx: 80-83 */
399 	{ DPU_IRQ_TYPE_HIST_DSPP_DONE, DSPP_1, DPU_INTR_HIST_DSPP_1_DONE, 2},
400 	{ DPU_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_1,
401 		DPU_INTR_HIST_DSPP_1_RSTSEQ_DONE, 2},
402 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
403 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
404 	/* irq_idx: 84-87 */
405 	{ DPU_IRQ_TYPE_HIST_DSPP_DONE, DSPP_2, DPU_INTR_HIST_DSPP_2_DONE, 2},
406 	{ DPU_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_2,
407 		DPU_INTR_HIST_DSPP_2_RSTSEQ_DONE, 2},
408 	{ DPU_IRQ_TYPE_HIST_DSPP_DONE, DSPP_3, DPU_INTR_HIST_DSPP_3_DONE, 2},
409 	{ DPU_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_3,
410 		DPU_INTR_HIST_DSPP_3_RSTSEQ_DONE, 2},
411 	/* irq_idx: 88-91 */
412 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
413 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
414 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
415 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
416 	/* irq_idx: 92-95 */
417 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
418 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
419 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
420 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 2},
421 
422 	/* BEGIN MAP_RANGE: 96-127 INTF_0_INTR */
423 	/* irq_idx: 96-99 */
424 	{ DPU_IRQ_TYPE_SFI_VIDEO_IN, INTF_0,
425 		DPU_INTR_VIDEO_INTO_STATIC, 3},
426 	{ DPU_IRQ_TYPE_SFI_VIDEO_OUT, INTF_0,
427 		DPU_INTR_VIDEO_OUTOF_STATIC, 3},
428 	{ DPU_IRQ_TYPE_SFI_CMD_0_IN, INTF_0,
429 		DPU_INTR_DSICMD_0_INTO_STATIC, 3},
430 	{ DPU_IRQ_TYPE_SFI_CMD_0_OUT, INTF_0,
431 		DPU_INTR_DSICMD_0_OUTOF_STATIC, 3},
432 	/* irq_idx: 100-103 */
433 	{ DPU_IRQ_TYPE_SFI_CMD_1_IN, INTF_0,
434 		DPU_INTR_DSICMD_1_INTO_STATIC, 3},
435 	{ DPU_IRQ_TYPE_SFI_CMD_1_OUT, INTF_0,
436 		DPU_INTR_DSICMD_1_OUTOF_STATIC, 3},
437 	{ DPU_IRQ_TYPE_SFI_CMD_2_IN, INTF_0,
438 		DPU_INTR_DSICMD_2_INTO_STATIC, 3},
439 	{ DPU_IRQ_TYPE_SFI_CMD_2_OUT, INTF_0,
440 		DPU_INTR_DSICMD_2_OUTOF_STATIC, 3},
441 	/* irq_idx: 104-107 */
442 	{ DPU_IRQ_TYPE_PROG_LINE, INTF_0, DPU_INTR_PROG_LINE, 3},
443 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
444 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
445 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
446 	/* irq_idx: 108-111 */
447 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
448 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
449 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
450 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
451 	/* irq_idx: 112-115 */
452 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
453 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
454 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
455 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
456 	/* irq_idx: 116-119 */
457 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
458 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
459 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
460 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
461 	/* irq_idx: 120-123 */
462 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
463 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
464 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
465 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
466 	/* irq_idx: 124-127 */
467 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
468 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
469 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
470 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 3},
471 
472 	/* BEGIN MAP_RANGE: 128-159 INTF_1_INTR */
473 	/* irq_idx: 128-131 */
474 	{ DPU_IRQ_TYPE_SFI_VIDEO_IN, INTF_1,
475 		DPU_INTR_VIDEO_INTO_STATIC, 4},
476 	{ DPU_IRQ_TYPE_SFI_VIDEO_OUT, INTF_1,
477 		DPU_INTR_VIDEO_OUTOF_STATIC, 4},
478 	{ DPU_IRQ_TYPE_SFI_CMD_0_IN, INTF_1,
479 		DPU_INTR_DSICMD_0_INTO_STATIC, 4},
480 	{ DPU_IRQ_TYPE_SFI_CMD_0_OUT, INTF_1,
481 		DPU_INTR_DSICMD_0_OUTOF_STATIC, 4},
482 	/* irq_idx: 132-135 */
483 	{ DPU_IRQ_TYPE_SFI_CMD_1_IN, INTF_1,
484 		DPU_INTR_DSICMD_1_INTO_STATIC, 4},
485 	{ DPU_IRQ_TYPE_SFI_CMD_1_OUT, INTF_1,
486 		DPU_INTR_DSICMD_1_OUTOF_STATIC, 4},
487 	{ DPU_IRQ_TYPE_SFI_CMD_2_IN, INTF_1,
488 		DPU_INTR_DSICMD_2_INTO_STATIC, 4},
489 	{ DPU_IRQ_TYPE_SFI_CMD_2_OUT, INTF_1,
490 		DPU_INTR_DSICMD_2_OUTOF_STATIC, 4},
491 	/* irq_idx: 136-139 */
492 	{ DPU_IRQ_TYPE_PROG_LINE, INTF_1, DPU_INTR_PROG_LINE, 4},
493 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
494 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
495 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
496 	/* irq_idx: 140-143 */
497 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
498 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
499 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
500 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
501 	/* irq_idx: 144-147 */
502 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
503 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
504 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
505 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
506 	/* irq_idx: 148-151 */
507 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
508 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
509 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
510 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
511 	/* irq_idx: 152-155 */
512 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
513 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
514 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
515 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
516 	/* irq_idx: 156-159 */
517 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
518 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
519 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
520 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 4},
521 
522 	/* BEGIN MAP_RANGE: 160-191 INTF_2_INTR */
523 	/* irq_idx: 160-163 */
524 	{ DPU_IRQ_TYPE_SFI_VIDEO_IN, INTF_2,
525 		DPU_INTR_VIDEO_INTO_STATIC, 5},
526 	{ DPU_IRQ_TYPE_SFI_VIDEO_OUT, INTF_2,
527 		DPU_INTR_VIDEO_OUTOF_STATIC, 5},
528 	{ DPU_IRQ_TYPE_SFI_CMD_0_IN, INTF_2,
529 		DPU_INTR_DSICMD_0_INTO_STATIC, 5},
530 	{ DPU_IRQ_TYPE_SFI_CMD_0_OUT, INTF_2,
531 		DPU_INTR_DSICMD_0_OUTOF_STATIC, 5},
532 	/* irq_idx: 164-167 */
533 	{ DPU_IRQ_TYPE_SFI_CMD_1_IN, INTF_2,
534 		DPU_INTR_DSICMD_1_INTO_STATIC, 5},
535 	{ DPU_IRQ_TYPE_SFI_CMD_1_OUT, INTF_2,
536 		DPU_INTR_DSICMD_1_OUTOF_STATIC, 5},
537 	{ DPU_IRQ_TYPE_SFI_CMD_2_IN, INTF_2,
538 		DPU_INTR_DSICMD_2_INTO_STATIC, 5},
539 	{ DPU_IRQ_TYPE_SFI_CMD_2_OUT, INTF_2,
540 		DPU_INTR_DSICMD_2_OUTOF_STATIC, 5},
541 	/* irq_idx: 168-171 */
542 	{ DPU_IRQ_TYPE_PROG_LINE, INTF_2, DPU_INTR_PROG_LINE, 5},
543 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
544 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
545 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
546 	/* irq_idx: 172-175 */
547 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
548 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
549 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
550 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
551 	/* irq_idx: 176-179 */
552 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
553 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
554 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
555 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
556 	/* irq_idx: 180-183 */
557 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
558 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
559 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
560 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
561 	/* irq_idx: 184-187 */
562 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
563 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
564 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
565 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
566 	/* irq_idx: 188-191 */
567 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
568 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
569 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
570 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 5},
571 
572 	/* BEGIN MAP_RANGE: 192-223 INTF_3_INTR */
573 	/* irq_idx: 192-195 */
574 	{ DPU_IRQ_TYPE_SFI_VIDEO_IN, INTF_3,
575 		DPU_INTR_VIDEO_INTO_STATIC, 6},
576 	{ DPU_IRQ_TYPE_SFI_VIDEO_OUT, INTF_3,
577 		DPU_INTR_VIDEO_OUTOF_STATIC, 6},
578 	{ DPU_IRQ_TYPE_SFI_CMD_0_IN, INTF_3,
579 		DPU_INTR_DSICMD_0_INTO_STATIC, 6},
580 	{ DPU_IRQ_TYPE_SFI_CMD_0_OUT, INTF_3,
581 		DPU_INTR_DSICMD_0_OUTOF_STATIC, 6},
582 	/* irq_idx: 196-199 */
583 	{ DPU_IRQ_TYPE_SFI_CMD_1_IN, INTF_3,
584 		DPU_INTR_DSICMD_1_INTO_STATIC, 6},
585 	{ DPU_IRQ_TYPE_SFI_CMD_1_OUT, INTF_3,
586 		DPU_INTR_DSICMD_1_OUTOF_STATIC, 6},
587 	{ DPU_IRQ_TYPE_SFI_CMD_2_IN, INTF_3,
588 		DPU_INTR_DSICMD_2_INTO_STATIC, 6},
589 	{ DPU_IRQ_TYPE_SFI_CMD_2_OUT, INTF_3,
590 		DPU_INTR_DSICMD_2_OUTOF_STATIC, 6},
591 	/* irq_idx: 200-203 */
592 	{ DPU_IRQ_TYPE_PROG_LINE, INTF_3, DPU_INTR_PROG_LINE, 6},
593 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
594 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
595 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
596 	/* irq_idx: 204-207 */
597 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
598 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
599 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
600 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
601 	/* irq_idx: 208-211 */
602 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
603 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
604 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
605 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
606 	/* irq_idx: 212-215 */
607 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
608 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
609 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
610 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
611 	/* irq_idx: 216-219 */
612 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
613 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
614 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
615 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
616 	/* irq_idx: 220-223 */
617 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
618 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
619 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
620 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 6},
621 
622 	/* BEGIN MAP_RANGE: 224-255 INTF_4_INTR */
623 	/* irq_idx: 224-227 */
624 	{ DPU_IRQ_TYPE_SFI_VIDEO_IN, INTF_4,
625 		DPU_INTR_VIDEO_INTO_STATIC, 7},
626 	{ DPU_IRQ_TYPE_SFI_VIDEO_OUT, INTF_4,
627 		DPU_INTR_VIDEO_OUTOF_STATIC, 7},
628 	{ DPU_IRQ_TYPE_SFI_CMD_0_IN, INTF_4,
629 		DPU_INTR_DSICMD_0_INTO_STATIC, 7},
630 	{ DPU_IRQ_TYPE_SFI_CMD_0_OUT, INTF_4,
631 		DPU_INTR_DSICMD_0_OUTOF_STATIC, 7},
632 	/* irq_idx: 228-231 */
633 	{ DPU_IRQ_TYPE_SFI_CMD_1_IN, INTF_4,
634 		DPU_INTR_DSICMD_1_INTO_STATIC, 7},
635 	{ DPU_IRQ_TYPE_SFI_CMD_1_OUT, INTF_4,
636 		DPU_INTR_DSICMD_1_OUTOF_STATIC, 7},
637 	{ DPU_IRQ_TYPE_SFI_CMD_2_IN, INTF_4,
638 		DPU_INTR_DSICMD_2_INTO_STATIC, 7},
639 	{ DPU_IRQ_TYPE_SFI_CMD_2_OUT, INTF_4,
640 		DPU_INTR_DSICMD_2_OUTOF_STATIC, 7},
641 	/* irq_idx: 232-235 */
642 	{ DPU_IRQ_TYPE_PROG_LINE, INTF_4, DPU_INTR_PROG_LINE, 7},
643 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
644 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
645 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
646 	/* irq_idx: 236-239 */
647 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
648 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
649 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
650 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
651 	/* irq_idx: 240-243 */
652 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
653 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
654 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
655 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
656 	/* irq_idx: 244-247 */
657 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
658 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
659 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
660 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
661 	/* irq_idx: 248-251 */
662 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
663 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
664 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
665 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
666 	/* irq_idx: 252-255 */
667 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
668 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
669 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
670 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 7},
671 
672 	/* BEGIN MAP_RANGE: 256-287 AD4_0_INTR */
673 	/* irq_idx: 256-259 */
674 	{ DPU_IRQ_TYPE_AD4_BL_DONE, DSPP_0, DPU_INTR_BACKLIGHT_UPDATED, 8},
675 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
676 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
677 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
678 	/* irq_idx: 260-263 */
679 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
680 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
681 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
682 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
683 	/* irq_idx: 264-267 */
684 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
685 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
686 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
687 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
688 	/* irq_idx: 268-271 */
689 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
690 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
691 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
692 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
693 	/* irq_idx: 272-275 */
694 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
695 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
696 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
697 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
698 	/* irq_idx: 276-279 */
699 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
700 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
701 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
702 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
703 	/* irq_idx: 280-283 */
704 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
705 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
706 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
707 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
708 	/* irq_idx: 284-287 */
709 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
710 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
711 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
712 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 8},
713 
714 	/* BEGIN MAP_RANGE: 288-319 AD4_1_INTR */
715 	/* irq_idx: 288-291 */
716 	{ DPU_IRQ_TYPE_AD4_BL_DONE, DSPP_1, DPU_INTR_BACKLIGHT_UPDATED, 9},
717 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
718 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
719 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
720 	/* irq_idx: 292-295 */
721 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
722 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
723 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
724 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
725 	/* irq_idx: 296-299 */
726 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
727 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
728 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
729 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
730 	/* irq_idx: 300-303 */
731 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
732 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
733 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
734 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
735 	/* irq_idx: 304-307 */
736 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
737 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
738 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
739 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
740 	/* irq_idx: 308-311 */
741 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
742 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
743 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
744 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
745 	/* irq_idx: 312-315 */
746 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
747 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
748 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
749 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
750 	/* irq_idx: 315-319 */
751 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
752 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
753 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
754 	{ DPU_IRQ_TYPE_RESERVED, 0, 0, 9},
755 };
756 
757 static int dpu_hw_intr_irqidx_lookup(enum dpu_intr_type intr_type,
758 		u32 instance_idx)
759 {
760 	int i;
761 
762 	for (i = 0; i < ARRAY_SIZE(dpu_irq_map); i++) {
763 		if (intr_type == dpu_irq_map[i].intr_type &&
764 			instance_idx == dpu_irq_map[i].instance_idx)
765 			return i;
766 	}
767 
768 	pr_debug("IRQ lookup fail!! intr_type=%d, instance_idx=%d\n",
769 			intr_type, instance_idx);
770 	return -EINVAL;
771 }
772 
773 static void dpu_hw_intr_dispatch_irq(struct dpu_hw_intr *intr,
774 		void (*cbfunc)(void *, int),
775 		void *arg)
776 {
777 	int reg_idx;
778 	int irq_idx;
779 	int start_idx;
780 	int end_idx;
781 	u32 irq_status;
782 	unsigned long irq_flags;
783 
784 	if (!intr)
785 		return;
786 
787 	/*
788 	 * The dispatcher will save the IRQ status before calling here.
789 	 * Now need to go through each IRQ status and find matching
790 	 * irq lookup index.
791 	 */
792 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
793 	for (reg_idx = 0; reg_idx < ARRAY_SIZE(dpu_intr_set); reg_idx++) {
794 		irq_status = intr->save_irq_status[reg_idx];
795 
796 		/*
797 		 * Each Interrupt register has a range of 32 indexes, and
798 		 * that is static for dpu_irq_map.
799 		 */
800 		start_idx = reg_idx * 32;
801 		end_idx = start_idx + 32;
802 
803 		if (!test_bit(reg_idx, &intr->irq_mask) ||
804 			start_idx >= ARRAY_SIZE(dpu_irq_map))
805 			continue;
806 
807 		/*
808 		 * Search through matching intr status from irq map.
809 		 * start_idx and end_idx defined the search range in
810 		 * the dpu_irq_map.
811 		 */
812 		for (irq_idx = start_idx;
813 				(irq_idx < end_idx) && irq_status;
814 				irq_idx++)
815 			if ((irq_status & dpu_irq_map[irq_idx].irq_mask) &&
816 				(dpu_irq_map[irq_idx].reg_idx == reg_idx)) {
817 				/*
818 				 * Once a match on irq mask, perform a callback
819 				 * to the given cbfunc. cbfunc will take care
820 				 * the interrupt status clearing. If cbfunc is
821 				 * not provided, then the interrupt clearing
822 				 * is here.
823 				 */
824 				if (cbfunc)
825 					cbfunc(arg, irq_idx);
826 				else
827 					intr->ops.clear_intr_status_nolock(
828 							intr, irq_idx);
829 
830 				/*
831 				 * When callback finish, clear the irq_status
832 				 * with the matching mask. Once irq_status
833 				 * is all cleared, the search can be stopped.
834 				 */
835 				irq_status &= ~dpu_irq_map[irq_idx].irq_mask;
836 			}
837 	}
838 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
839 }
840 
841 static int dpu_hw_intr_enable_irq(struct dpu_hw_intr *intr, int irq_idx)
842 {
843 	int reg_idx;
844 	unsigned long irq_flags;
845 	const struct dpu_intr_reg *reg;
846 	const struct dpu_irq_type *irq;
847 	const char *dbgstr = NULL;
848 	uint32_t cache_irq_mask;
849 
850 	if (!intr)
851 		return -EINVAL;
852 
853 	if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(dpu_irq_map)) {
854 		pr_err("invalid IRQ index: [%d]\n", irq_idx);
855 		return -EINVAL;
856 	}
857 
858 	irq = &dpu_irq_map[irq_idx];
859 	reg_idx = irq->reg_idx;
860 	reg = &dpu_intr_set[reg_idx];
861 
862 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
863 	cache_irq_mask = intr->cache_irq_mask[reg_idx];
864 	if (cache_irq_mask & irq->irq_mask) {
865 		dbgstr = "DPU IRQ already set:";
866 	} else {
867 		dbgstr = "DPU IRQ enabled:";
868 
869 		cache_irq_mask |= irq->irq_mask;
870 		/* Cleaning any pending interrupt */
871 		DPU_REG_WRITE(&intr->hw, reg->clr_off, irq->irq_mask);
872 		/* Enabling interrupts with the new mask */
873 		DPU_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
874 
875 		/* ensure register write goes through */
876 		wmb();
877 
878 		intr->cache_irq_mask[reg_idx] = cache_irq_mask;
879 	}
880 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
881 
882 	pr_debug("%s MASK:0x%.8x, CACHE-MASK:0x%.8x\n", dbgstr,
883 			irq->irq_mask, cache_irq_mask);
884 
885 	return 0;
886 }
887 
888 static int dpu_hw_intr_disable_irq_nolock(struct dpu_hw_intr *intr, int irq_idx)
889 {
890 	int reg_idx;
891 	const struct dpu_intr_reg *reg;
892 	const struct dpu_irq_type *irq;
893 	const char *dbgstr = NULL;
894 	uint32_t cache_irq_mask;
895 
896 	if (!intr)
897 		return -EINVAL;
898 
899 	if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(dpu_irq_map)) {
900 		pr_err("invalid IRQ index: [%d]\n", irq_idx);
901 		return -EINVAL;
902 	}
903 
904 	irq = &dpu_irq_map[irq_idx];
905 	reg_idx = irq->reg_idx;
906 	reg = &dpu_intr_set[reg_idx];
907 
908 	cache_irq_mask = intr->cache_irq_mask[reg_idx];
909 	if ((cache_irq_mask & irq->irq_mask) == 0) {
910 		dbgstr = "DPU IRQ is already cleared:";
911 	} else {
912 		dbgstr = "DPU IRQ mask disable:";
913 
914 		cache_irq_mask &= ~irq->irq_mask;
915 		/* Disable interrupts based on the new mask */
916 		DPU_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
917 		/* Cleaning any pending interrupt */
918 		DPU_REG_WRITE(&intr->hw, reg->clr_off, irq->irq_mask);
919 
920 		/* ensure register write goes through */
921 		wmb();
922 
923 		intr->cache_irq_mask[reg_idx] = cache_irq_mask;
924 	}
925 
926 	pr_debug("%s MASK:0x%.8x, CACHE-MASK:0x%.8x\n", dbgstr,
927 			irq->irq_mask, cache_irq_mask);
928 
929 	return 0;
930 }
931 
932 static int dpu_hw_intr_disable_irq(struct dpu_hw_intr *intr, int irq_idx)
933 {
934 	unsigned long irq_flags;
935 
936 	if (!intr)
937 		return -EINVAL;
938 
939 	if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(dpu_irq_map)) {
940 		pr_err("invalid IRQ index: [%d]\n", irq_idx);
941 		return -EINVAL;
942 	}
943 
944 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
945 	dpu_hw_intr_disable_irq_nolock(intr, irq_idx);
946 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
947 
948 	return 0;
949 }
950 
951 static int dpu_hw_intr_clear_irqs(struct dpu_hw_intr *intr)
952 {
953 	int i;
954 
955 	if (!intr)
956 		return -EINVAL;
957 
958 	for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) {
959 		if (test_bit(i, &intr->irq_mask))
960 			DPU_REG_WRITE(&intr->hw,
961 					dpu_intr_set[i].clr_off, 0xffffffff);
962 	}
963 
964 	/* ensure register writes go through */
965 	wmb();
966 
967 	return 0;
968 }
969 
970 static int dpu_hw_intr_disable_irqs(struct dpu_hw_intr *intr)
971 {
972 	int i;
973 
974 	if (!intr)
975 		return -EINVAL;
976 
977 	for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) {
978 		if (test_bit(i, &intr->irq_mask))
979 			DPU_REG_WRITE(&intr->hw,
980 					dpu_intr_set[i].en_off, 0x00000000);
981 	}
982 
983 	/* ensure register writes go through */
984 	wmb();
985 
986 	return 0;
987 }
988 
989 static void dpu_hw_intr_get_interrupt_statuses(struct dpu_hw_intr *intr)
990 {
991 	int i;
992 	u32 enable_mask;
993 	unsigned long irq_flags;
994 
995 	if (!intr)
996 		return;
997 
998 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
999 	for (i = 0; i < ARRAY_SIZE(dpu_intr_set); i++) {
1000 		if (!test_bit(i, &intr->irq_mask))
1001 			continue;
1002 
1003 		/* Read interrupt status */
1004 		intr->save_irq_status[i] = DPU_REG_READ(&intr->hw,
1005 				dpu_intr_set[i].status_off);
1006 
1007 		/* Read enable mask */
1008 		enable_mask = DPU_REG_READ(&intr->hw, dpu_intr_set[i].en_off);
1009 
1010 		/* and clear the interrupt */
1011 		if (intr->save_irq_status[i])
1012 			DPU_REG_WRITE(&intr->hw, dpu_intr_set[i].clr_off,
1013 					intr->save_irq_status[i]);
1014 
1015 		/* Finally update IRQ status based on enable mask */
1016 		intr->save_irq_status[i] &= enable_mask;
1017 	}
1018 
1019 	/* ensure register writes go through */
1020 	wmb();
1021 
1022 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
1023 }
1024 
1025 static void dpu_hw_intr_clear_intr_status_nolock(struct dpu_hw_intr *intr,
1026 		int irq_idx)
1027 {
1028 	int reg_idx;
1029 
1030 	if (!intr)
1031 		return;
1032 
1033 	reg_idx = dpu_irq_map[irq_idx].reg_idx;
1034 	DPU_REG_WRITE(&intr->hw, dpu_intr_set[reg_idx].clr_off,
1035 			dpu_irq_map[irq_idx].irq_mask);
1036 
1037 	/* ensure register writes go through */
1038 	wmb();
1039 }
1040 
1041 static u32 dpu_hw_intr_get_interrupt_status(struct dpu_hw_intr *intr,
1042 		int irq_idx, bool clear)
1043 {
1044 	int reg_idx;
1045 	unsigned long irq_flags;
1046 	u32 intr_status;
1047 
1048 	if (!intr)
1049 		return 0;
1050 
1051 	if (irq_idx >= ARRAY_SIZE(dpu_irq_map) || irq_idx < 0) {
1052 		pr_err("invalid IRQ index: [%d]\n", irq_idx);
1053 		return 0;
1054 	}
1055 
1056 	spin_lock_irqsave(&intr->irq_lock, irq_flags);
1057 
1058 	reg_idx = dpu_irq_map[irq_idx].reg_idx;
1059 	intr_status = DPU_REG_READ(&intr->hw,
1060 			dpu_intr_set[reg_idx].status_off) &
1061 					dpu_irq_map[irq_idx].irq_mask;
1062 	if (intr_status && clear)
1063 		DPU_REG_WRITE(&intr->hw, dpu_intr_set[reg_idx].clr_off,
1064 				intr_status);
1065 
1066 	/* ensure register writes go through */
1067 	wmb();
1068 
1069 	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
1070 
1071 	return intr_status;
1072 }
1073 
1074 static void __setup_intr_ops(struct dpu_hw_intr_ops *ops)
1075 {
1076 	ops->irq_idx_lookup = dpu_hw_intr_irqidx_lookup;
1077 	ops->enable_irq = dpu_hw_intr_enable_irq;
1078 	ops->disable_irq = dpu_hw_intr_disable_irq;
1079 	ops->dispatch_irqs = dpu_hw_intr_dispatch_irq;
1080 	ops->clear_all_irqs = dpu_hw_intr_clear_irqs;
1081 	ops->disable_all_irqs = dpu_hw_intr_disable_irqs;
1082 	ops->get_interrupt_statuses = dpu_hw_intr_get_interrupt_statuses;
1083 	ops->clear_intr_status_nolock = dpu_hw_intr_clear_intr_status_nolock;
1084 	ops->get_interrupt_status = dpu_hw_intr_get_interrupt_status;
1085 }
1086 
1087 static void __intr_offset(struct dpu_mdss_cfg *m,
1088 		void __iomem *addr, struct dpu_hw_blk_reg_map *hw)
1089 {
1090 	hw->base_off = addr;
1091 	hw->blk_off = m->mdp[0].base;
1092 	hw->hwversion = m->hwversion;
1093 }
1094 
1095 struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
1096 		struct dpu_mdss_cfg *m)
1097 {
1098 	struct dpu_hw_intr *intr;
1099 
1100 	if (!addr || !m)
1101 		return ERR_PTR(-EINVAL);
1102 
1103 	intr = kzalloc(sizeof(*intr), GFP_KERNEL);
1104 	if (!intr)
1105 		return ERR_PTR(-ENOMEM);
1106 
1107 	__intr_offset(m, addr, &intr->hw);
1108 	__setup_intr_ops(&intr->ops);
1109 
1110 	intr->irq_idx_tbl_size = ARRAY_SIZE(dpu_irq_map);
1111 
1112 	intr->cache_irq_mask = kcalloc(ARRAY_SIZE(dpu_intr_set), sizeof(u32),
1113 			GFP_KERNEL);
1114 	if (intr->cache_irq_mask == NULL) {
1115 		kfree(intr);
1116 		return ERR_PTR(-ENOMEM);
1117 	}
1118 
1119 	intr->save_irq_status = kcalloc(ARRAY_SIZE(dpu_intr_set), sizeof(u32),
1120 			GFP_KERNEL);
1121 	if (intr->save_irq_status == NULL) {
1122 		kfree(intr->cache_irq_mask);
1123 		kfree(intr);
1124 		return ERR_PTR(-ENOMEM);
1125 	}
1126 
1127 	intr->irq_mask = m->mdss_irqs;
1128 	spin_lock_init(&intr->irq_lock);
1129 
1130 	return intr;
1131 }
1132 
1133 void dpu_hw_intr_destroy(struct dpu_hw_intr *intr)
1134 {
1135 	if (intr) {
1136 		kfree(intr->cache_irq_mask);
1137 		kfree(intr->save_irq_status);
1138 		kfree(intr);
1139 	}
1140 }
1141 
1142