1 /*
2  * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 and
6  * only version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 
14 #include "mdp5_kms.h"
15 #include "mdp5_cfg.h"
16 
17 struct mdp5_cfg_handler {
18 	int revision;
19 	struct mdp5_cfg config;
20 };
21 
22 /* mdp5_cfg must be exposed (used in mdp5.xml.h) */
23 const struct mdp5_cfg_hw *mdp5_cfg = NULL;
24 
25 const struct mdp5_cfg_hw msm8x74v1_config = {
26 	.name = "msm8x74v1",
27 	.mdp = {
28 		.count = 1,
29 		.caps = MDP_CAP_SMP |
30 			0,
31 	},
32 	.smp = {
33 		.mmb_count = 22,
34 		.mmb_size = 4096,
35 		.clients = {
36 			[SSPP_VIG0] =  1, [SSPP_VIG1] =  4, [SSPP_VIG2] =  7,
37 			[SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
38 			[SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18,
39 		},
40 	},
41 	.ctl = {
42 		.count = 5,
43 		.base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
44 		.flush_hw_mask = 0x0003ffff,
45 	},
46 	.pipe_vig = {
47 		.count = 3,
48 		.base = { 0x01100, 0x01500, 0x01900 },
49 		.caps = MDP_PIPE_CAP_HFLIP |
50 			MDP_PIPE_CAP_VFLIP |
51 			MDP_PIPE_CAP_SCALE |
52 			MDP_PIPE_CAP_CSC   |
53 			0,
54 	},
55 	.pipe_rgb = {
56 		.count = 3,
57 		.base = { 0x01d00, 0x02100, 0x02500 },
58 		.caps = MDP_PIPE_CAP_HFLIP |
59 			MDP_PIPE_CAP_VFLIP |
60 			MDP_PIPE_CAP_SCALE |
61 			0,
62 	},
63 	.pipe_dma = {
64 		.count = 2,
65 		.base = { 0x02900, 0x02d00 },
66 		.caps = MDP_PIPE_CAP_HFLIP |
67 			MDP_PIPE_CAP_VFLIP |
68 			0,
69 	},
70 	.lm = {
71 		.count = 5,
72 		.base = { 0x03100, 0x03500, 0x03900, 0x03d00, 0x04100 },
73 		.instances = {
74 				{ .id = 0, .pp = 0, .dspp = 0,
75 				  .caps = MDP_LM_CAP_DISPLAY, },
76 				{ .id = 1, .pp = 1, .dspp = 1,
77 				  .caps = MDP_LM_CAP_DISPLAY, },
78 				{ .id = 2, .pp = 2, .dspp = 2,
79 				  .caps = MDP_LM_CAP_DISPLAY, },
80 				{ .id = 3, .pp = -1, .dspp = -1,
81 				  .caps = MDP_LM_CAP_WB },
82 				{ .id = 4, .pp = -1, .dspp = -1,
83 				  .caps = MDP_LM_CAP_WB },
84 			     },
85 		.nb_stages = 5,
86 		.max_width = 2048,
87 		.max_height = 0xFFFF,
88 	},
89 	.dspp = {
90 		.count = 3,
91 		.base = { 0x04500, 0x04900, 0x04d00 },
92 	},
93 	.pp = {
94 		.count = 3,
95 		.base = { 0x21a00, 0x21b00, 0x21c00 },
96 	},
97 	.intf = {
98 		.base = { 0x21000, 0x21200, 0x21400, 0x21600 },
99 		.connect = {
100 			[0] = INTF_eDP,
101 			[1] = INTF_DSI,
102 			[2] = INTF_DSI,
103 			[3] = INTF_HDMI,
104 		},
105 	},
106 	.max_clk = 200000000,
107 };
108 
109 const struct mdp5_cfg_hw msm8x74v2_config = {
110 	.name = "msm8x74",
111 	.mdp = {
112 		.count = 1,
113 		.caps = MDP_CAP_SMP |
114 			0,
115 	},
116 	.smp = {
117 		.mmb_count = 22,
118 		.mmb_size = 4096,
119 		.clients = {
120 			[SSPP_VIG0] =  1, [SSPP_VIG1] =  4, [SSPP_VIG2] =  7,
121 			[SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
122 			[SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18,
123 		},
124 	},
125 	.ctl = {
126 		.count = 5,
127 		.base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
128 		.flush_hw_mask = 0x0003ffff,
129 	},
130 	.pipe_vig = {
131 		.count = 3,
132 		.base = { 0x01100, 0x01500, 0x01900 },
133 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
134 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
135 				MDP_PIPE_CAP_DECIMATION,
136 	},
137 	.pipe_rgb = {
138 		.count = 3,
139 		.base = { 0x01d00, 0x02100, 0x02500 },
140 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
141 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
142 	},
143 	.pipe_dma = {
144 		.count = 2,
145 		.base = { 0x02900, 0x02d00 },
146 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
147 	},
148 	.lm = {
149 		.count = 5,
150 		.base = { 0x03100, 0x03500, 0x03900, 0x03d00, 0x04100 },
151 		.instances = {
152 				{ .id = 0, .pp = 0, .dspp = 0,
153 				  .caps = MDP_LM_CAP_DISPLAY, },
154 				{ .id = 1, .pp = 1, .dspp = 1,
155 				  .caps = MDP_LM_CAP_DISPLAY, },
156 				{ .id = 2, .pp = 2, .dspp = 2,
157 				  .caps = MDP_LM_CAP_DISPLAY, },
158 				{ .id = 3, .pp = -1, .dspp = -1,
159 				  .caps = MDP_LM_CAP_WB, },
160 				{ .id = 4, .pp = -1, .dspp = -1,
161 				  .caps = MDP_LM_CAP_WB, },
162 			     },
163 		.nb_stages = 5,
164 		.max_width = 2048,
165 		.max_height = 0xFFFF,
166 	},
167 	.dspp = {
168 		.count = 3,
169 		.base = { 0x04500, 0x04900, 0x04d00 },
170 	},
171 	.ad = {
172 		.count = 2,
173 		.base = { 0x13000, 0x13200 },
174 	},
175 	.pp = {
176 		.count = 3,
177 		.base = { 0x12c00, 0x12d00, 0x12e00 },
178 	},
179 	.intf = {
180 		.base = { 0x12400, 0x12600, 0x12800, 0x12a00 },
181 		.connect = {
182 			[0] = INTF_eDP,
183 			[1] = INTF_DSI,
184 			[2] = INTF_DSI,
185 			[3] = INTF_HDMI,
186 		},
187 	},
188 	.max_clk = 200000000,
189 };
190 
191 const struct mdp5_cfg_hw apq8084_config = {
192 	.name = "apq8084",
193 	.mdp = {
194 		.count = 1,
195 		.caps = MDP_CAP_SMP |
196 			MDP_CAP_SRC_SPLIT |
197 			0,
198 	},
199 	.smp = {
200 		.mmb_count = 44,
201 		.mmb_size = 8192,
202 		.clients = {
203 			[SSPP_VIG0] =  1, [SSPP_VIG1] =  4,
204 			[SSPP_VIG2] =  7, [SSPP_VIG3] = 19,
205 			[SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
206 			[SSPP_RGB0] = 16, [SSPP_RGB1] = 17,
207 			[SSPP_RGB2] = 18, [SSPP_RGB3] = 22,
208 		},
209 		.reserved_state[0] = GENMASK(7, 0),	/* first 8 MMBs */
210 		.reserved = {
211 			/* Two SMP blocks are statically tied to RGB pipes: */
212 			[16] = 2, [17] = 2, [18] = 2, [22] = 2,
213 		},
214 	},
215 	.ctl = {
216 		.count = 5,
217 		.base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
218 		.flush_hw_mask = 0x003fffff,
219 	},
220 	.pipe_vig = {
221 		.count = 4,
222 		.base = { 0x01100, 0x01500, 0x01900, 0x01d00 },
223 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
224 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
225 				MDP_PIPE_CAP_DECIMATION,
226 	},
227 	.pipe_rgb = {
228 		.count = 4,
229 		.base = { 0x02100, 0x02500, 0x02900, 0x02d00 },
230 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
231 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
232 	},
233 	.pipe_dma = {
234 		.count = 2,
235 		.base = { 0x03100, 0x03500 },
236 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
237 	},
238 	.lm = {
239 		.count = 6,
240 		.base = { 0x03900, 0x03d00, 0x04100, 0x04500, 0x04900, 0x04d00 },
241 		.instances = {
242 				{ .id = 0, .pp = 0, .dspp = 0,
243 				  .caps = MDP_LM_CAP_DISPLAY |
244 					  MDP_LM_CAP_PAIR, },
245 				{ .id = 1, .pp = 1, .dspp = 1,
246 				  .caps = MDP_LM_CAP_DISPLAY, },
247 				{ .id = 2, .pp = 2, .dspp = 2,
248 				  .caps = MDP_LM_CAP_DISPLAY |
249 					  MDP_LM_CAP_PAIR, },
250 				{ .id = 3, .pp = -1, .dspp = -1,
251 				  .caps = MDP_LM_CAP_WB, },
252 				{ .id = 4, .pp = -1, .dspp = -1,
253 				  .caps = MDP_LM_CAP_WB, },
254 				{ .id = 5, .pp = 3, .dspp = 3,
255 				  .caps = MDP_LM_CAP_DISPLAY, },
256 			     },
257 		.nb_stages = 5,
258 		.max_width = 2048,
259 		.max_height = 0xFFFF,
260 	},
261 	.dspp = {
262 		.count = 4,
263 		.base = { 0x05100, 0x05500, 0x05900, 0x05d00 },
264 
265 	},
266 	.ad = {
267 		.count = 3,
268 		.base = { 0x13400, 0x13600, 0x13800 },
269 	},
270 	.pp = {
271 		.count = 4,
272 		.base = { 0x12e00, 0x12f00, 0x13000, 0x13100 },
273 	},
274 	.intf = {
275 		.base = { 0x12400, 0x12600, 0x12800, 0x12a00, 0x12c00 },
276 		.connect = {
277 			[0] = INTF_eDP,
278 			[1] = INTF_DSI,
279 			[2] = INTF_DSI,
280 			[3] = INTF_HDMI,
281 		},
282 	},
283 	.max_clk = 320000000,
284 };
285 
286 const struct mdp5_cfg_hw msm8x16_config = {
287 	.name = "msm8x16",
288 	.mdp = {
289 		.count = 1,
290 		.base = { 0x0 },
291 		.caps = MDP_CAP_SMP |
292 			0,
293 	},
294 	.smp = {
295 		.mmb_count = 8,
296 		.mmb_size = 8192,
297 		.clients = {
298 			[SSPP_VIG0] = 1, [SSPP_DMA0] = 4,
299 			[SSPP_RGB0] = 7, [SSPP_RGB1] = 8,
300 		},
301 	},
302 	.ctl = {
303 		.count = 5,
304 		.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
305 		.flush_hw_mask = 0x4003ffff,
306 	},
307 	.pipe_vig = {
308 		.count = 1,
309 		.base = { 0x04000 },
310 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
311 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
312 				MDP_PIPE_CAP_DECIMATION,
313 	},
314 	.pipe_rgb = {
315 		.count = 2,
316 		.base = { 0x14000, 0x16000 },
317 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
318 				MDP_PIPE_CAP_DECIMATION,
319 	},
320 	.pipe_dma = {
321 		.count = 1,
322 		.base = { 0x24000 },
323 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
324 	},
325 	.lm = {
326 		.count = 2, /* LM0 and LM3 */
327 		.base = { 0x44000, 0x47000 },
328 		.instances = {
329 				{ .id = 0, .pp = 0, .dspp = 0,
330 				  .caps = MDP_LM_CAP_DISPLAY, },
331 				{ .id = 3, .pp = -1, .dspp = -1,
332 				  .caps = MDP_LM_CAP_WB },
333 			     },
334 		.nb_stages = 8,
335 		.max_width = 2048,
336 		.max_height = 0xFFFF,
337 	},
338 	.dspp = {
339 		.count = 1,
340 		.base = { 0x54000 },
341 
342 	},
343 	.intf = {
344 		.base = { 0x00000, 0x6a800 },
345 		.connect = {
346 			[0] = INTF_DISABLED,
347 			[1] = INTF_DSI,
348 		},
349 	},
350 	.max_clk = 320000000,
351 };
352 
353 const struct mdp5_cfg_hw msm8x94_config = {
354 	.name = "msm8x94",
355 	.mdp = {
356 		.count = 1,
357 		.caps = MDP_CAP_SMP |
358 			MDP_CAP_SRC_SPLIT |
359 			0,
360 	},
361 	.smp = {
362 		.mmb_count = 44,
363 		.mmb_size = 8192,
364 		.clients = {
365 			[SSPP_VIG0] =  1, [SSPP_VIG1] =  4,
366 			[SSPP_VIG2] =  7, [SSPP_VIG3] = 19,
367 			[SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
368 			[SSPP_RGB0] = 16, [SSPP_RGB1] = 17,
369 			[SSPP_RGB2] = 18, [SSPP_RGB3] = 22,
370 		},
371 		.reserved_state[0] = GENMASK(23, 0),	/* first 24 MMBs */
372 		.reserved = {
373 			 [1] = 1,  [4] = 1,  [7] = 1, [19] = 1,
374 			[16] = 5, [17] = 5, [18] = 5, [22] = 5,
375 		},
376 	},
377 	.ctl = {
378 		.count = 5,
379 		.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
380 		.flush_hw_mask = 0xf0ffffff,
381 	},
382 	.pipe_vig = {
383 		.count = 4,
384 		.base = { 0x04000, 0x06000, 0x08000, 0x0a000 },
385 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
386 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
387 				MDP_PIPE_CAP_DECIMATION,
388 	},
389 	.pipe_rgb = {
390 		.count = 4,
391 		.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
392 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
393 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
394 	},
395 	.pipe_dma = {
396 		.count = 2,
397 		.base = { 0x24000, 0x26000 },
398 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
399 	},
400 	.lm = {
401 		.count = 6,
402 		.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
403 		.instances = {
404 				{ .id = 0, .pp = 0, .dspp = 0,
405 				  .caps = MDP_LM_CAP_DISPLAY |
406 					  MDP_LM_CAP_PAIR, },
407 				{ .id = 1, .pp = 1, .dspp = 1,
408 				  .caps = MDP_LM_CAP_DISPLAY, },
409 				{ .id = 2, .pp = 2, .dspp = 2,
410 				  .caps = MDP_LM_CAP_DISPLAY |
411 					  MDP_LM_CAP_PAIR, },
412 				{ .id = 3, .pp = -1, .dspp = -1,
413 				  .caps = MDP_LM_CAP_WB, },
414 				{ .id = 4, .pp = -1, .dspp = -1,
415 				  .caps = MDP_LM_CAP_WB, },
416 				{ .id = 5, .pp = 3, .dspp = 3,
417 				  .caps = MDP_LM_CAP_DISPLAY, },
418 			     },
419 		.nb_stages = 8,
420 		.max_width = 2048,
421 		.max_height = 0xFFFF,
422 	},
423 	.dspp = {
424 		.count = 4,
425 		.base = { 0x54000, 0x56000, 0x58000, 0x5a000 },
426 
427 	},
428 	.ad = {
429 		.count = 3,
430 		.base = { 0x78000, 0x78800, 0x79000 },
431 	},
432 	.pp = {
433 		.count = 4,
434 		.base = { 0x70000, 0x70800, 0x71000, 0x71800 },
435 	},
436 	.intf = {
437 		.base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800, 0x6c000 },
438 		.connect = {
439 			[0] = INTF_DISABLED,
440 			[1] = INTF_DSI,
441 			[2] = INTF_DSI,
442 			[3] = INTF_HDMI,
443 		},
444 	},
445 	.max_clk = 400000000,
446 };
447 
448 const struct mdp5_cfg_hw msm8x96_config = {
449 	.name = "msm8x96",
450 	.mdp = {
451 		.count = 1,
452 		.caps = MDP_CAP_DSC |
453 			MDP_CAP_CDM |
454 			MDP_CAP_SRC_SPLIT |
455 			0,
456 	},
457 	.ctl = {
458 		.count = 5,
459 		.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
460 		.flush_hw_mask = 0xf4ffffff,
461 	},
462 	.pipe_vig = {
463 		.count = 4,
464 		.base = { 0x04000, 0x06000, 0x08000, 0x0a000 },
465 		.caps = MDP_PIPE_CAP_HFLIP	|
466 			MDP_PIPE_CAP_VFLIP	|
467 			MDP_PIPE_CAP_SCALE	|
468 			MDP_PIPE_CAP_CSC	|
469 			MDP_PIPE_CAP_DECIMATION	|
470 			MDP_PIPE_CAP_SW_PIX_EXT	|
471 			0,
472 	},
473 	.pipe_rgb = {
474 		.count = 4,
475 		.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
476 		.caps = MDP_PIPE_CAP_HFLIP	|
477 			MDP_PIPE_CAP_VFLIP	|
478 			MDP_PIPE_CAP_SCALE	|
479 			MDP_PIPE_CAP_DECIMATION	|
480 			MDP_PIPE_CAP_SW_PIX_EXT	|
481 			0,
482 	},
483 	.pipe_dma = {
484 		.count = 2,
485 		.base = { 0x24000, 0x26000 },
486 		.caps = MDP_PIPE_CAP_HFLIP	|
487 			MDP_PIPE_CAP_VFLIP	|
488 			MDP_PIPE_CAP_SW_PIX_EXT	|
489 			0,
490 	},
491 	.pipe_cursor = {
492 		.count = 2,
493 		.base = { 0x34000, 0x36000 },
494 		.caps = MDP_PIPE_CAP_HFLIP	|
495 			MDP_PIPE_CAP_VFLIP	|
496 			MDP_PIPE_CAP_SW_PIX_EXT	|
497 			MDP_PIPE_CAP_CURSOR	|
498 			0,
499 	},
500 
501 	.lm = {
502 		.count = 6,
503 		.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
504 		.instances = {
505 				{ .id = 0, .pp = 0, .dspp = 0,
506 				  .caps = MDP_LM_CAP_DISPLAY |
507 					  MDP_LM_CAP_PAIR, },
508 				{ .id = 1, .pp = 1, .dspp = 1,
509 				  .caps = MDP_LM_CAP_DISPLAY, },
510 				{ .id = 2, .pp = 2, .dspp = -1,
511 				  .caps = MDP_LM_CAP_DISPLAY |
512 					  MDP_LM_CAP_PAIR, },
513 				{ .id = 3, .pp = -1, .dspp = -1,
514 				  .caps = MDP_LM_CAP_WB, },
515 				{ .id = 4, .pp = -1, .dspp = -1,
516 				  .caps = MDP_LM_CAP_WB, },
517 				{ .id = 5, .pp = 3, .dspp = -1,
518 				  .caps = MDP_LM_CAP_DISPLAY, },
519 			     },
520 		.nb_stages = 8,
521 		.max_width = 2560,
522 		.max_height = 0xFFFF,
523 	},
524 	.dspp = {
525 		.count = 2,
526 		.base = { 0x54000, 0x56000 },
527 	},
528 	.ad = {
529 		.count = 3,
530 		.base = { 0x78000, 0x78800, 0x79000 },
531 	},
532 	.pp = {
533 		.count = 4,
534 		.base = { 0x70000, 0x70800, 0x71000, 0x71800 },
535 	},
536 	.cdm = {
537 		.count = 1,
538 		.base = { 0x79200 },
539 	},
540 	.dsc = {
541 		.count = 2,
542 		.base = { 0x80000, 0x80400 },
543 	},
544 	.intf = {
545 		.base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800, 0x6c000 },
546 		.connect = {
547 			[0] = INTF_DISABLED,
548 			[1] = INTF_DSI,
549 			[2] = INTF_DSI,
550 			[3] = INTF_HDMI,
551 		},
552 	},
553 	.max_clk = 412500000,
554 };
555 
556 static const struct mdp5_cfg_handler cfg_handlers[] = {
557 	{ .revision = 0, .config = { .hw = &msm8x74v1_config } },
558 	{ .revision = 2, .config = { .hw = &msm8x74v2_config } },
559 	{ .revision = 3, .config = { .hw = &apq8084_config } },
560 	{ .revision = 6, .config = { .hw = &msm8x16_config } },
561 	{ .revision = 9, .config = { .hw = &msm8x94_config } },
562 	{ .revision = 7, .config = { .hw = &msm8x96_config } },
563 };
564 
565 static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev);
566 
567 const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(struct mdp5_cfg_handler *cfg_handler)
568 {
569 	return cfg_handler->config.hw;
570 }
571 
572 struct mdp5_cfg *mdp5_cfg_get_config(struct mdp5_cfg_handler *cfg_handler)
573 {
574 	return &cfg_handler->config;
575 }
576 
577 int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_handler)
578 {
579 	return cfg_handler->revision;
580 }
581 
582 void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_handler)
583 {
584 	kfree(cfg_handler);
585 }
586 
587 struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
588 		uint32_t major, uint32_t minor)
589 {
590 	struct drm_device *dev = mdp5_kms->dev;
591 	struct platform_device *pdev = to_platform_device(dev->dev);
592 	struct mdp5_cfg_handler *cfg_handler;
593 	struct mdp5_cfg_platform *pconfig;
594 	int i, ret = 0;
595 
596 	cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL);
597 	if (unlikely(!cfg_handler)) {
598 		ret = -ENOMEM;
599 		goto fail;
600 	}
601 
602 	if (major != 1) {
603 		dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n",
604 				major, minor);
605 		ret = -ENXIO;
606 		goto fail;
607 	}
608 
609 	/* only after mdp5_cfg global pointer's init can we access the hw */
610 	for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) {
611 		if (cfg_handlers[i].revision != minor)
612 			continue;
613 		mdp5_cfg = cfg_handlers[i].config.hw;
614 
615 		break;
616 	}
617 	if (unlikely(!mdp5_cfg)) {
618 		dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n",
619 				major, minor);
620 		ret = -ENXIO;
621 		goto fail;
622 	}
623 
624 	cfg_handler->revision = minor;
625 	cfg_handler->config.hw = mdp5_cfg;
626 
627 	pconfig = mdp5_get_config(pdev);
628 	memcpy(&cfg_handler->config.platform, pconfig, sizeof(*pconfig));
629 
630 	DBG("MDP5: %s hw config selected", mdp5_cfg->name);
631 
632 	return cfg_handler;
633 
634 fail:
635 	if (cfg_handler)
636 		mdp5_cfg_destroy(cfg_handler);
637 
638 	return NULL;
639 }
640 
641 static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev)
642 {
643 	static struct mdp5_cfg_platform config = {};
644 
645 	config.iommu = iommu_domain_alloc(&platform_bus_type);
646 	if (config.iommu) {
647 		config.iommu->geometry.aperture_start = 0x1000;
648 		config.iommu->geometry.aperture_end = 0xffffffff;
649 	}
650 
651 	return &config;
652 }
653