]>
Commit | Line | Data |
---|---|---|
2e362e17 SV |
1 | /* |
2 | * Copyright (c) 2014 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 msm8x74_config = { | |
26 | .name = "msm8x74", | |
27 | .smp = { | |
28 | .mmb_count = 22, | |
29 | .mmb_size = 4096, | |
30 | }, | |
31 | .ctl = { | |
32 | .count = 5, | |
33 | .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, | |
34 | }, | |
35 | .pipe_vig = { | |
36 | .count = 3, | |
37 | .base = { 0x01200, 0x01600, 0x01a00 }, | |
38 | }, | |
39 | .pipe_rgb = { | |
40 | .count = 3, | |
41 | .base = { 0x01e00, 0x02200, 0x02600 }, | |
42 | }, | |
43 | .pipe_dma = { | |
44 | .count = 2, | |
45 | .base = { 0x02a00, 0x02e00 }, | |
46 | }, | |
47 | .lm = { | |
48 | .count = 5, | |
49 | .base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 }, | |
50 | .nb_stages = 5, | |
51 | }, | |
52 | .dspp = { | |
53 | .count = 3, | |
54 | .base = { 0x04600, 0x04a00, 0x04e00 }, | |
55 | }, | |
56 | .ad = { | |
57 | .count = 2, | |
58 | .base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */ | |
59 | }, | |
60 | .intf = { | |
61 | .count = 4, | |
62 | .base = { 0x12500, 0x12700, 0x12900, 0x12b00 }, | |
63 | }, | |
64 | .max_clk = 200000000, | |
65 | }; | |
66 | ||
67 | const struct mdp5_cfg_hw apq8084_config = { | |
68 | .name = "apq8084", | |
69 | .smp = { | |
70 | .mmb_count = 44, | |
71 | .mmb_size = 8192, | |
72 | .reserved_state[0] = GENMASK(7, 0), /* first 8 MMBs */ | |
73 | .reserved[CID_RGB0] = 2, | |
74 | .reserved[CID_RGB1] = 2, | |
75 | .reserved[CID_RGB2] = 2, | |
76 | .reserved[CID_RGB3] = 2, | |
77 | }, | |
78 | .ctl = { | |
79 | .count = 5, | |
80 | .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, | |
81 | }, | |
82 | .pipe_vig = { | |
83 | .count = 4, | |
84 | .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 }, | |
85 | }, | |
86 | .pipe_rgb = { | |
87 | .count = 4, | |
88 | .base = { 0x02200, 0x02600, 0x02a00, 0x02e00 }, | |
89 | }, | |
90 | .pipe_dma = { | |
91 | .count = 2, | |
92 | .base = { 0x03200, 0x03600 }, | |
93 | }, | |
94 | .lm = { | |
95 | .count = 6, | |
96 | .base = { 0x03a00, 0x03e00, 0x04200, 0x04600, 0x04a00, 0x04e00 }, | |
97 | .nb_stages = 5, | |
98 | }, | |
99 | .dspp = { | |
100 | .count = 4, | |
101 | .base = { 0x05200, 0x05600, 0x05a00, 0x05e00 }, | |
102 | ||
103 | }, | |
104 | .ad = { | |
105 | .count = 3, | |
106 | .base = { 0x13500, 0x13700, 0x13900 }, | |
107 | }, | |
108 | .intf = { | |
109 | .count = 5, | |
110 | .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 }, | |
111 | }, | |
112 | .max_clk = 320000000, | |
113 | }; | |
114 | ||
115 | static const struct mdp5_cfg_handler cfg_handlers[] = { | |
116 | { .revision = 0, .config = { .hw = &msm8x74_config } }, | |
117 | { .revision = 2, .config = { .hw = &msm8x74_config } }, | |
118 | { .revision = 3, .config = { .hw = &apq8084_config } }, | |
119 | }; | |
120 | ||
121 | ||
122 | static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev); | |
123 | ||
124 | const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(void *cfg_hnd) | |
125 | { | |
126 | struct mdp5_cfg_handler *cfg_handler = cfg_hnd; | |
127 | ||
128 | return cfg_handler->config.hw; | |
129 | } | |
130 | ||
131 | struct mdp5_cfg *mdp5_cfg_get_config(void *cfg_hnd) | |
132 | { | |
133 | struct mdp5_cfg_handler *cfg_handler = cfg_hnd; | |
134 | ||
135 | return &cfg_handler->config; | |
136 | } | |
137 | ||
138 | int mdp5_cfg_get_hw_rev(void *cfg_hnd) | |
139 | { | |
140 | struct mdp5_cfg_handler *cfg_handler = cfg_hnd; | |
141 | ||
142 | return cfg_handler->revision; | |
143 | } | |
144 | ||
145 | void mdp5_cfg_destroy(void *cfg_hnd) | |
146 | { | |
147 | struct mdp5_cfg_handler *cfg_handler = cfg_hnd; | |
148 | ||
149 | kfree(cfg_handler); | |
150 | } | |
151 | ||
152 | void *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, | |
153 | uint32_t major, uint32_t minor) | |
154 | { | |
155 | struct drm_device *dev = mdp5_kms->dev; | |
156 | struct platform_device *pdev = dev->platformdev; | |
157 | struct mdp5_cfg_handler *cfg_handler; | |
158 | struct mdp5_cfg_platform *pconfig; | |
159 | int i, ret = 0; | |
160 | ||
161 | cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL); | |
162 | if (unlikely(!cfg_handler)) { | |
163 | ret = -ENOMEM; | |
164 | goto fail; | |
165 | } | |
166 | ||
167 | if (major != 1) { | |
168 | dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n", | |
169 | major, minor); | |
170 | ret = -ENXIO; | |
171 | goto fail; | |
172 | } | |
173 | ||
174 | /* only after mdp5_cfg global pointer's init can we access the hw */ | |
175 | for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) { | |
176 | if (cfg_handlers[i].revision != minor) | |
177 | continue; | |
178 | mdp5_cfg = cfg_handlers[i].config.hw; | |
179 | ||
180 | break; | |
181 | } | |
182 | if (unlikely(!mdp5_cfg)) { | |
183 | dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n", | |
184 | major, minor); | |
185 | ret = -ENXIO; | |
186 | goto fail; | |
187 | } | |
188 | ||
189 | cfg_handler->revision = minor; | |
190 | cfg_handler->config.hw = mdp5_cfg; | |
191 | ||
192 | pconfig = mdp5_get_config(pdev); | |
193 | memcpy(&cfg_handler->config.platform, pconfig, sizeof(*pconfig)); | |
194 | ||
195 | DBG("MDP5: %s hw config selected", mdp5_cfg->name); | |
196 | ||
197 | return cfg_handler; | |
198 | ||
199 | fail: | |
200 | if (cfg_handler) | |
201 | mdp5_cfg_destroy(cfg_handler); | |
202 | ||
203 | return NULL; | |
204 | } | |
205 | ||
206 | static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev) | |
207 | { | |
208 | static struct mdp5_cfg_platform config = {}; | |
209 | #ifdef CONFIG_OF | |
210 | /* TODO */ | |
211 | #endif | |
212 | config.iommu = iommu_domain_alloc(&platform_bus_type); | |
213 | ||
214 | return &config; | |
215 | } |