• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		.nb_stages = 5,
74 	},
75 	.dspp = {
76 		.count = 3,
77 		.base = { 0x04500, 0x04900, 0x04d00 },
78 	},
79 	.pp = {
80 		.count = 3,
81 		.base = { 0x21a00, 0x21b00, 0x21c00 },
82 	},
83 	.intf = {
84 		.base = { 0x21000, 0x21200, 0x21400, 0x21600 },
85 		.connect = {
86 			[0] = INTF_eDP,
87 			[1] = INTF_DSI,
88 			[2] = INTF_DSI,
89 			[3] = INTF_HDMI,
90 		},
91 	},
92 	.max_clk = 200000000,
93 };
94 
95 const struct mdp5_cfg_hw msm8x74v2_config = {
96 	.name = "msm8x74",
97 	.mdp = {
98 		.count = 1,
99 		.caps = MDP_CAP_SMP |
100 			0,
101 	},
102 	.smp = {
103 		.mmb_count = 22,
104 		.mmb_size = 4096,
105 		.clients = {
106 			[SSPP_VIG0] =  1, [SSPP_VIG1] =  4, [SSPP_VIG2] =  7,
107 			[SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
108 			[SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18,
109 		},
110 	},
111 	.ctl = {
112 		.count = 5,
113 		.base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
114 		.flush_hw_mask = 0x0003ffff,
115 	},
116 	.pipe_vig = {
117 		.count = 3,
118 		.base = { 0x01100, 0x01500, 0x01900 },
119 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
120 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
121 				MDP_PIPE_CAP_DECIMATION,
122 	},
123 	.pipe_rgb = {
124 		.count = 3,
125 		.base = { 0x01d00, 0x02100, 0x02500 },
126 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
127 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
128 	},
129 	.pipe_dma = {
130 		.count = 2,
131 		.base = { 0x02900, 0x02d00 },
132 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
133 	},
134 	.lm = {
135 		.count = 5,
136 		.base = { 0x03100, 0x03500, 0x03900, 0x03d00, 0x04100 },
137 		.nb_stages = 5,
138 		.max_width = 2048,
139 		.max_height = 0xFFFF,
140 	},
141 	.dspp = {
142 		.count = 3,
143 		.base = { 0x04500, 0x04900, 0x04d00 },
144 	},
145 	.ad = {
146 		.count = 2,
147 		.base = { 0x13000, 0x13200 },
148 	},
149 	.pp = {
150 		.count = 3,
151 		.base = { 0x12c00, 0x12d00, 0x12e00 },
152 	},
153 	.intf = {
154 		.base = { 0x12400, 0x12600, 0x12800, 0x12a00 },
155 		.connect = {
156 			[0] = INTF_eDP,
157 			[1] = INTF_DSI,
158 			[2] = INTF_DSI,
159 			[3] = INTF_HDMI,
160 		},
161 	},
162 	.max_clk = 200000000,
163 };
164 
165 const struct mdp5_cfg_hw apq8084_config = {
166 	.name = "apq8084",
167 	.mdp = {
168 		.count = 1,
169 		.caps = MDP_CAP_SMP |
170 			0,
171 	},
172 	.smp = {
173 		.mmb_count = 44,
174 		.mmb_size = 8192,
175 		.clients = {
176 			[SSPP_VIG0] =  1, [SSPP_VIG1] =  4,
177 			[SSPP_VIG2] =  7, [SSPP_VIG3] = 19,
178 			[SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
179 			[SSPP_RGB0] = 16, [SSPP_RGB1] = 17,
180 			[SSPP_RGB2] = 18, [SSPP_RGB3] = 22,
181 		},
182 		.reserved_state[0] = GENMASK(7, 0),	/* first 8 MMBs */
183 		.reserved = {
184 			/* Two SMP blocks are statically tied to RGB pipes: */
185 			[16] = 2, [17] = 2, [18] = 2, [22] = 2,
186 		},
187 	},
188 	.ctl = {
189 		.count = 5,
190 		.base = { 0x00500, 0x00600, 0x00700, 0x00800, 0x00900 },
191 		.flush_hw_mask = 0x003fffff,
192 	},
193 	.pipe_vig = {
194 		.count = 4,
195 		.base = { 0x01100, 0x01500, 0x01900, 0x01d00 },
196 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
197 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
198 				MDP_PIPE_CAP_DECIMATION,
199 	},
200 	.pipe_rgb = {
201 		.count = 4,
202 		.base = { 0x02100, 0x02500, 0x02900, 0x02d00 },
203 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
204 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
205 	},
206 	.pipe_dma = {
207 		.count = 2,
208 		.base = { 0x03100, 0x03500 },
209 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
210 	},
211 	.lm = {
212 		.count = 6,
213 		.base = { 0x03900, 0x03d00, 0x04100, 0x04500, 0x04900, 0x04d00 },
214 		.nb_stages = 5,
215 		.max_width = 2048,
216 		.max_height = 0xFFFF,
217 	},
218 	.dspp = {
219 		.count = 4,
220 		.base = { 0x05100, 0x05500, 0x05900, 0x05d00 },
221 
222 	},
223 	.ad = {
224 		.count = 3,
225 		.base = { 0x13400, 0x13600, 0x13800 },
226 	},
227 	.pp = {
228 		.count = 4,
229 		.base = { 0x12e00, 0x12f00, 0x13000, 0x13100 },
230 	},
231 	.intf = {
232 		.base = { 0x12400, 0x12600, 0x12800, 0x12a00, 0x12c00 },
233 		.connect = {
234 			[0] = INTF_eDP,
235 			[1] = INTF_DSI,
236 			[2] = INTF_DSI,
237 			[3] = INTF_HDMI,
238 		},
239 	},
240 	.max_clk = 320000000,
241 };
242 
243 const struct mdp5_cfg_hw msm8x16_config = {
244 	.name = "msm8x16",
245 	.mdp = {
246 		.count = 1,
247 		.base = { 0x0 },
248 		.caps = MDP_CAP_SMP |
249 			0,
250 	},
251 	.smp = {
252 		.mmb_count = 8,
253 		.mmb_size = 8192,
254 		.clients = {
255 			[SSPP_VIG0] = 1, [SSPP_DMA0] = 4,
256 			[SSPP_RGB0] = 7, [SSPP_RGB1] = 8,
257 		},
258 	},
259 	.ctl = {
260 		.count = 5,
261 		.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
262 		.flush_hw_mask = 0x4003ffff,
263 	},
264 	.pipe_vig = {
265 		.count = 1,
266 		.base = { 0x04000 },
267 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
268 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
269 				MDP_PIPE_CAP_DECIMATION,
270 	},
271 	.pipe_rgb = {
272 		.count = 2,
273 		.base = { 0x14000, 0x16000 },
274 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
275 				MDP_PIPE_CAP_DECIMATION,
276 	},
277 	.pipe_dma = {
278 		.count = 1,
279 		.base = { 0x24000 },
280 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
281 	},
282 	.lm = {
283 		.count = 2, /* LM0 and LM3 */
284 		.base = { 0x44000, 0x47000 },
285 		.nb_stages = 8,
286 		.max_width = 2048,
287 		.max_height = 0xFFFF,
288 	},
289 	.dspp = {
290 		.count = 1,
291 		.base = { 0x54000 },
292 
293 	},
294 	.intf = {
295 		.base = { 0x00000, 0x6a800 },
296 		.connect = {
297 			[0] = INTF_DISABLED,
298 			[1] = INTF_DSI,
299 		},
300 	},
301 	.max_clk = 320000000,
302 };
303 
304 const struct mdp5_cfg_hw msm8x94_config = {
305 	.name = "msm8x94",
306 	.mdp = {
307 		.count = 1,
308 		.caps = MDP_CAP_SMP |
309 			0,
310 	},
311 	.smp = {
312 		.mmb_count = 44,
313 		.mmb_size = 8192,
314 		.clients = {
315 			[SSPP_VIG0] =  1, [SSPP_VIG1] =  4,
316 			[SSPP_VIG2] =  7, [SSPP_VIG3] = 19,
317 			[SSPP_DMA0] = 10, [SSPP_DMA1] = 13,
318 			[SSPP_RGB0] = 16, [SSPP_RGB1] = 17,
319 			[SSPP_RGB2] = 18, [SSPP_RGB3] = 22,
320 		},
321 		.reserved_state[0] = GENMASK(23, 0),	/* first 24 MMBs */
322 		.reserved = {
323 			 [1] = 1,  [4] = 1,  [7] = 1, [19] = 1,
324 			[16] = 5, [17] = 5, [18] = 5, [22] = 5,
325 		},
326 	},
327 	.ctl = {
328 		.count = 5,
329 		.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
330 		.flush_hw_mask = 0xf0ffffff,
331 	},
332 	.pipe_vig = {
333 		.count = 4,
334 		.base = { 0x04000, 0x06000, 0x08000, 0x0a000 },
335 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
336 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC |
337 				MDP_PIPE_CAP_DECIMATION,
338 	},
339 	.pipe_rgb = {
340 		.count = 4,
341 		.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
342 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
343 				MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION,
344 	},
345 	.pipe_dma = {
346 		.count = 2,
347 		.base = { 0x24000, 0x26000 },
348 		.caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP,
349 	},
350 	.lm = {
351 		.count = 6,
352 		.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
353 		.nb_stages = 8,
354 		.max_width = 2048,
355 		.max_height = 0xFFFF,
356 	},
357 	.dspp = {
358 		.count = 4,
359 		.base = { 0x54000, 0x56000, 0x58000, 0x5a000 },
360 
361 	},
362 	.ad = {
363 		.count = 3,
364 		.base = { 0x78000, 0x78800, 0x79000 },
365 	},
366 	.pp = {
367 		.count = 4,
368 		.base = { 0x70000, 0x70800, 0x71000, 0x71800 },
369 	},
370 	.intf = {
371 		.base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800, 0x6c000 },
372 		.connect = {
373 			[0] = INTF_DISABLED,
374 			[1] = INTF_DSI,
375 			[2] = INTF_DSI,
376 			[3] = INTF_HDMI,
377 		},
378 	},
379 	.max_clk = 400000000,
380 };
381 
382 const struct mdp5_cfg_hw msm8x96_config = {
383 	.name = "msm8x96",
384 	.mdp = {
385 		.count = 1,
386 		.caps = MDP_CAP_DSC |
387 			MDP_CAP_CDM |
388 			0,
389 	},
390 	.ctl = {
391 		.count = 5,
392 		.base = { 0x01000, 0x01200, 0x01400, 0x01600, 0x01800 },
393 		.flush_hw_mask = 0xf4ffffff,
394 	},
395 	.pipe_vig = {
396 		.count = 4,
397 		.base = { 0x04000, 0x06000, 0x08000, 0x0a000 },
398 		.caps = MDP_PIPE_CAP_HFLIP	|
399 			MDP_PIPE_CAP_VFLIP	|
400 			MDP_PIPE_CAP_SCALE	|
401 			MDP_PIPE_CAP_CSC	|
402 			MDP_PIPE_CAP_DECIMATION	|
403 			MDP_PIPE_CAP_SW_PIX_EXT	|
404 			0,
405 	},
406 	.pipe_rgb = {
407 		.count = 4,
408 		.base = { 0x14000, 0x16000, 0x18000, 0x1a000 },
409 		.caps = MDP_PIPE_CAP_HFLIP	|
410 			MDP_PIPE_CAP_VFLIP	|
411 			MDP_PIPE_CAP_SCALE	|
412 			MDP_PIPE_CAP_DECIMATION	|
413 			MDP_PIPE_CAP_SW_PIX_EXT	|
414 			0,
415 	},
416 	.pipe_dma = {
417 		.count = 2,
418 		.base = { 0x24000, 0x26000 },
419 		.caps = MDP_PIPE_CAP_HFLIP	|
420 			MDP_PIPE_CAP_VFLIP	|
421 			MDP_PIPE_CAP_SW_PIX_EXT	|
422 			0,
423 	},
424 	.lm = {
425 		.count = 6,
426 		.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
427 		.nb_stages = 8,
428 		.max_width = 2560,
429 		.max_height = 0xFFFF,
430 	},
431 	.dspp = {
432 		.count = 2,
433 		.base = { 0x54000, 0x56000 },
434 	},
435 	.ad = {
436 		.count = 3,
437 		.base = { 0x78000, 0x78800, 0x79000 },
438 	},
439 	.pp = {
440 		.count = 4,
441 		.base = { 0x70000, 0x70800, 0x71000, 0x71800 },
442 	},
443 	.cdm = {
444 		.count = 1,
445 		.base = { 0x79200 },
446 	},
447 	.dsc = {
448 		.count = 2,
449 		.base = { 0x80000, 0x80400 },
450 	},
451 	.intf = {
452 		.base = { 0x6a000, 0x6a800, 0x6b000, 0x6b800, 0x6c000 },
453 		.connect = {
454 			[0] = INTF_DISABLED,
455 			[1] = INTF_DSI,
456 			[2] = INTF_DSI,
457 			[3] = INTF_HDMI,
458 		},
459 	},
460 	.max_clk = 412500000,
461 };
462 
463 static const struct mdp5_cfg_handler cfg_handlers[] = {
464 	{ .revision = 0, .config = { .hw = &msm8x74v1_config } },
465 	{ .revision = 2, .config = { .hw = &msm8x74v2_config } },
466 	{ .revision = 3, .config = { .hw = &apq8084_config } },
467 	{ .revision = 6, .config = { .hw = &msm8x16_config } },
468 	{ .revision = 9, .config = { .hw = &msm8x94_config } },
469 	{ .revision = 7, .config = { .hw = &msm8x96_config } },
470 };
471 
472 static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev);
473 
mdp5_cfg_get_hw_config(struct mdp5_cfg_handler * cfg_handler)474 const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(struct mdp5_cfg_handler *cfg_handler)
475 {
476 	return cfg_handler->config.hw;
477 }
478 
mdp5_cfg_get_config(struct mdp5_cfg_handler * cfg_handler)479 struct mdp5_cfg *mdp5_cfg_get_config(struct mdp5_cfg_handler *cfg_handler)
480 {
481 	return &cfg_handler->config;
482 }
483 
mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler * cfg_handler)484 int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_handler)
485 {
486 	return cfg_handler->revision;
487 }
488 
mdp5_cfg_destroy(struct mdp5_cfg_handler * cfg_handler)489 void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_handler)
490 {
491 	kfree(cfg_handler);
492 }
493 
mdp5_cfg_init(struct mdp5_kms * mdp5_kms,uint32_t major,uint32_t minor)494 struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
495 		uint32_t major, uint32_t minor)
496 {
497 	struct drm_device *dev = mdp5_kms->dev;
498 	struct platform_device *pdev = dev->platformdev;
499 	struct mdp5_cfg_handler *cfg_handler;
500 	struct mdp5_cfg_platform *pconfig;
501 	int i, ret = 0;
502 
503 	cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL);
504 	if (unlikely(!cfg_handler)) {
505 		ret = -ENOMEM;
506 		goto fail;
507 	}
508 
509 	if (major != 1) {
510 		dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n",
511 				major, minor);
512 		ret = -ENXIO;
513 		goto fail;
514 	}
515 
516 	/* only after mdp5_cfg global pointer's init can we access the hw */
517 	for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) {
518 		if (cfg_handlers[i].revision != minor)
519 			continue;
520 		mdp5_cfg = cfg_handlers[i].config.hw;
521 
522 		break;
523 	}
524 	if (unlikely(!mdp5_cfg)) {
525 		dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n",
526 				major, minor);
527 		ret = -ENXIO;
528 		goto fail;
529 	}
530 
531 	cfg_handler->revision = minor;
532 	cfg_handler->config.hw = mdp5_cfg;
533 
534 	pconfig = mdp5_get_config(pdev);
535 	memcpy(&cfg_handler->config.platform, pconfig, sizeof(*pconfig));
536 
537 	DBG("MDP5: %s hw config selected", mdp5_cfg->name);
538 
539 	return cfg_handler;
540 
541 fail:
542 	if (cfg_handler)
543 		mdp5_cfg_destroy(cfg_handler);
544 
545 	return NULL;
546 }
547 
mdp5_get_config(struct platform_device * dev)548 static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev)
549 {
550 	static struct mdp5_cfg_platform config = {};
551 
552 	config.iommu = iommu_domain_alloc(&platform_bus_type);
553 
554 	return &config;
555 }
556