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