]>
Commit | Line | Data |
---|---|---|
2e362e17 | 1 | /* |
02dfd9d2 | 2 | * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. |
2e362e17 SV |
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 msm8x74_config = { | |
26 | .name = "msm8x74", | |
f5253812 SV |
27 | .mdp = { |
28 | .count = 1, | |
29 | .base = { 0x00100 }, | |
30 | }, | |
2e362e17 SV |
31 | .smp = { |
32 | .mmb_count = 22, | |
33 | .mmb_size = 4096, | |
6fa6acdf SV |
34 | .clients = { |
35 | [SSPP_VIG0] = 1, [SSPP_VIG1] = 4, [SSPP_VIG2] = 7, | |
36 | [SSPP_DMA0] = 10, [SSPP_DMA1] = 13, | |
37 | [SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18, | |
38 | }, | |
2e362e17 SV |
39 | }, |
40 | .ctl = { | |
41 | .count = 5, | |
42 | .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, | |
389b09a1 | 43 | .flush_hw_mask = 0x0003ffff, |
2e362e17 SV |
44 | }, |
45 | .pipe_vig = { | |
46 | .count = 3, | |
47 | .base = { 0x01200, 0x01600, 0x01a00 }, | |
48 | }, | |
49 | .pipe_rgb = { | |
50 | .count = 3, | |
51 | .base = { 0x01e00, 0x02200, 0x02600 }, | |
52 | }, | |
53 | .pipe_dma = { | |
54 | .count = 2, | |
55 | .base = { 0x02a00, 0x02e00 }, | |
56 | }, | |
57 | .lm = { | |
58 | .count = 5, | |
59 | .base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 }, | |
60 | .nb_stages = 5, | |
61 | }, | |
62 | .dspp = { | |
63 | .count = 3, | |
64 | .base = { 0x04600, 0x04a00, 0x04e00 }, | |
65 | }, | |
66 | .ad = { | |
67 | .count = 2, | |
68 | .base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */ | |
69 | }, | |
38305907 HL |
70 | .pp = { |
71 | .count = 3, | |
72 | .base = { 0x12d00, 0x12e00, 0x12f00 }, | |
73 | }, | |
2e362e17 | 74 | .intf = { |
2e362e17 | 75 | .base = { 0x12500, 0x12700, 0x12900, 0x12b00 }, |
fe34464d SV |
76 | .connect = { |
77 | [0] = INTF_eDP, | |
78 | [1] = INTF_DSI, | |
79 | [2] = INTF_DSI, | |
80 | [3] = INTF_HDMI, | |
81 | }, | |
67ac0a2d | 82 | }, |
2e362e17 SV |
83 | .max_clk = 200000000, |
84 | }; | |
85 | ||
86 | const struct mdp5_cfg_hw apq8084_config = { | |
87 | .name = "apq8084", | |
f5253812 SV |
88 | .mdp = { |
89 | .count = 1, | |
90 | .base = { 0x00100 }, | |
91 | }, | |
2e362e17 SV |
92 | .smp = { |
93 | .mmb_count = 44, | |
94 | .mmb_size = 8192, | |
6fa6acdf SV |
95 | .clients = { |
96 | [SSPP_VIG0] = 1, [SSPP_VIG1] = 4, | |
97 | [SSPP_VIG2] = 7, [SSPP_VIG3] = 19, | |
98 | [SSPP_DMA0] = 10, [SSPP_DMA1] = 13, | |
99 | [SSPP_RGB0] = 16, [SSPP_RGB1] = 17, | |
100 | [SSPP_RGB2] = 18, [SSPP_RGB3] = 22, | |
101 | }, | |
2e362e17 | 102 | .reserved_state[0] = GENMASK(7, 0), /* first 8 MMBs */ |
6fa6acdf SV |
103 | .reserved = { |
104 | /* Two SMP blocks are statically tied to RGB pipes: */ | |
105 | [16] = 2, [17] = 2, [18] = 2, [22] = 2, | |
106 | }, | |
2e362e17 SV |
107 | }, |
108 | .ctl = { | |
109 | .count = 5, | |
110 | .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, | |
389b09a1 | 111 | .flush_hw_mask = 0x003fffff, |
2e362e17 SV |
112 | }, |
113 | .pipe_vig = { | |
114 | .count = 4, | |
115 | .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 }, | |
116 | }, | |
117 | .pipe_rgb = { | |
118 | .count = 4, | |
119 | .base = { 0x02200, 0x02600, 0x02a00, 0x02e00 }, | |
120 | }, | |
121 | .pipe_dma = { | |
122 | .count = 2, | |
123 | .base = { 0x03200, 0x03600 }, | |
124 | }, | |
125 | .lm = { | |
126 | .count = 6, | |
127 | .base = { 0x03a00, 0x03e00, 0x04200, 0x04600, 0x04a00, 0x04e00 }, | |
128 | .nb_stages = 5, | |
129 | }, | |
130 | .dspp = { | |
131 | .count = 4, | |
132 | .base = { 0x05200, 0x05600, 0x05a00, 0x05e00 }, | |
133 | ||
134 | }, | |
135 | .ad = { | |
136 | .count = 3, | |
137 | .base = { 0x13500, 0x13700, 0x13900 }, | |
138 | }, | |
38305907 HL |
139 | .pp = { |
140 | .count = 4, | |
141 | .base = { 0x12f00, 0x13000, 0x13100, 0x13200 }, | |
142 | }, | |
2e362e17 | 143 | .intf = { |
2e362e17 | 144 | .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 }, |
fe34464d SV |
145 | .connect = { |
146 | [0] = INTF_eDP, | |
147 | [1] = INTF_DSI, | |
148 | [2] = INTF_DSI, | |
149 | [3] = INTF_HDMI, | |
150 | }, | |
67ac0a2d | 151 | }, |
2e362e17 SV |
152 | .max_clk = 320000000, |
153 | }; | |
154 | ||
02dfd9d2 SV |
155 | const struct mdp5_cfg_hw msm8x16_config = { |
156 | .name = "msm8x16", | |
157 | .mdp = { | |
158 | .count = 1, | |
159 | .base = { 0x01000 }, | |
160 | }, | |
161 | .smp = { | |
162 | .mmb_count = 8, | |
163 | .mmb_size = 8192, | |
164 | .clients = { | |
165 | [SSPP_VIG0] = 1, [SSPP_DMA0] = 4, | |
166 | [SSPP_RGB0] = 7, [SSPP_RGB1] = 8, | |
167 | }, | |
168 | }, | |
169 | .ctl = { | |
170 | .count = 5, | |
171 | .base = { 0x02000, 0x02200, 0x02400, 0x02600, 0x02800 }, | |
172 | .flush_hw_mask = 0x4003ffff, | |
173 | }, | |
174 | .pipe_vig = { | |
175 | .count = 1, | |
176 | .base = { 0x05000 }, | |
177 | }, | |
178 | .pipe_rgb = { | |
179 | .count = 2, | |
180 | .base = { 0x15000, 0x17000 }, | |
181 | }, | |
182 | .pipe_dma = { | |
183 | .count = 1, | |
184 | .base = { 0x25000 }, | |
185 | }, | |
186 | .lm = { | |
187 | .count = 2, /* LM0 and LM3 */ | |
188 | .base = { 0x45000, 0x48000 }, | |
189 | .nb_stages = 5, | |
190 | }, | |
191 | .dspp = { | |
192 | .count = 1, | |
193 | .base = { 0x55000 }, | |
194 | ||
195 | }, | |
196 | .intf = { | |
fe34464d SV |
197 | .base = { 0x00000, 0x6b800 }, |
198 | .connect = { | |
199 | [0] = INTF_DISABLED, | |
200 | [1] = INTF_DSI, | |
201 | }, | |
02dfd9d2 | 202 | }, |
02dfd9d2 SV |
203 | .max_clk = 320000000, |
204 | }; | |
205 | ||
2e362e17 SV |
206 | static const struct mdp5_cfg_handler cfg_handlers[] = { |
207 | { .revision = 0, .config = { .hw = &msm8x74_config } }, | |
208 | { .revision = 2, .config = { .hw = &msm8x74_config } }, | |
209 | { .revision = 3, .config = { .hw = &apq8084_config } }, | |
02dfd9d2 | 210 | { .revision = 6, .config = { .hw = &msm8x16_config } }, |
2e362e17 SV |
211 | }; |
212 | ||
213 | ||
214 | static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev); | |
215 | ||
42238da8 | 216 | const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(struct mdp5_cfg_handler *cfg_handler) |
2e362e17 | 217 | { |
2e362e17 SV |
218 | return cfg_handler->config.hw; |
219 | } | |
220 | ||
42238da8 | 221 | struct mdp5_cfg *mdp5_cfg_get_config(struct mdp5_cfg_handler *cfg_handler) |
2e362e17 | 222 | { |
2e362e17 SV |
223 | return &cfg_handler->config; |
224 | } | |
225 | ||
42238da8 | 226 | int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_handler) |
2e362e17 | 227 | { |
2e362e17 SV |
228 | return cfg_handler->revision; |
229 | } | |
230 | ||
42238da8 | 231 | void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_handler) |
2e362e17 | 232 | { |
2e362e17 SV |
233 | kfree(cfg_handler); |
234 | } | |
235 | ||
42238da8 | 236 | struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, |
2e362e17 SV |
237 | uint32_t major, uint32_t minor) |
238 | { | |
239 | struct drm_device *dev = mdp5_kms->dev; | |
240 | struct platform_device *pdev = dev->platformdev; | |
241 | struct mdp5_cfg_handler *cfg_handler; | |
242 | struct mdp5_cfg_platform *pconfig; | |
243 | int i, ret = 0; | |
244 | ||
245 | cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL); | |
246 | if (unlikely(!cfg_handler)) { | |
247 | ret = -ENOMEM; | |
248 | goto fail; | |
249 | } | |
250 | ||
251 | if (major != 1) { | |
252 | dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n", | |
253 | major, minor); | |
254 | ret = -ENXIO; | |
255 | goto fail; | |
256 | } | |
257 | ||
258 | /* only after mdp5_cfg global pointer's init can we access the hw */ | |
259 | for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) { | |
260 | if (cfg_handlers[i].revision != minor) | |
261 | continue; | |
262 | mdp5_cfg = cfg_handlers[i].config.hw; | |
263 | ||
264 | break; | |
265 | } | |
266 | if (unlikely(!mdp5_cfg)) { | |
267 | dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n", | |
268 | major, minor); | |
269 | ret = -ENXIO; | |
270 | goto fail; | |
271 | } | |
272 | ||
273 | cfg_handler->revision = minor; | |
274 | cfg_handler->config.hw = mdp5_cfg; | |
275 | ||
276 | pconfig = mdp5_get_config(pdev); | |
277 | memcpy(&cfg_handler->config.platform, pconfig, sizeof(*pconfig)); | |
278 | ||
279 | DBG("MDP5: %s hw config selected", mdp5_cfg->name); | |
280 | ||
281 | return cfg_handler; | |
282 | ||
283 | fail: | |
284 | if (cfg_handler) | |
285 | mdp5_cfg_destroy(cfg_handler); | |
286 | ||
287 | return NULL; | |
288 | } | |
289 | ||
290 | static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev) | |
291 | { | |
292 | static struct mdp5_cfg_platform config = {}; | |
293 | #ifdef CONFIG_OF | |
294 | /* TODO */ | |
295 | #endif | |
296 | config.iommu = iommu_domain_alloc(&platform_bus_type); | |
297 | ||
298 | return &config; | |
299 | } |