Commit | Line | Data |
---|---|---|
4562236b HW |
1 | /* |
2 | * Copyright 2012-15 Advanced Micro Devices, Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | * OTHER DEALINGS IN THE SOFTWARE. | |
21 | * | |
22 | * Authors: AMD | |
23 | * | |
24 | */ | |
25 | ||
4fc4dca8 SR |
26 | #include <linux/slab.h> |
27 | ||
4562236b HW |
28 | #include "dce/dce_8_0_d.h" |
29 | #include "dce/dce_8_0_sh_mask.h" | |
30 | ||
31 | #include "dm_services.h" | |
32 | ||
33 | #include "link_encoder.h" | |
34 | #include "stream_encoder.h" | |
35 | ||
36 | #include "resource.h" | |
37 | #include "include/irq_service_interface.h" | |
38 | #include "irq/dce80/irq_service_dce80.h" | |
39 | #include "dce110/dce110_timing_generator.h" | |
4562236b HW |
40 | #include "dce110/dce110_resource.h" |
41 | #include "dce80/dce80_timing_generator.h" | |
c3489214 | 42 | #include "dce/dce_mem_input.h" |
4562236b HW |
43 | #include "dce/dce_link_encoder.h" |
44 | #include "dce/dce_stream_encoder.h" | |
e6303950 | 45 | #include "dce/dce_ipp.h" |
4562236b | 46 | #include "dce/dce_transform.h" |
ab3ee7a5 | 47 | #include "dce/dce_opp.h" |
4562236b HW |
48 | #include "dce/dce_clock_source.h" |
49 | #include "dce/dce_audio.h" | |
50 | #include "dce/dce_hwseq.h" | |
51 | #include "dce80/dce80_hw_sequencer.h" | |
792671d7 | 52 | #include "dce100/dce100_resource.h" |
4562236b HW |
53 | |
54 | #include "reg_helper.h" | |
55 | ||
d54ee946 | 56 | #include "dce/dce_dmcu.h" |
5c6ac711 | 57 | #include "dce/dce_aux.h" |
d54ee946 | 58 | #include "dce/dce_abm.h" |
c85e6e54 | 59 | #include "dce/dce_i2c.h" |
4562236b HW |
60 | /* TODO remove this include */ |
61 | ||
62 | #ifndef mmMC_HUB_RDREQ_DMIF_LIMIT | |
63 | #include "gmc/gmc_7_1_d.h" | |
64 | #include "gmc/gmc_7_1_sh_mask.h" | |
65 | #endif | |
66 | ||
67 | #ifndef mmDP_DPHY_INTERNAL_CTRL | |
68 | #define mmDP_DPHY_INTERNAL_CTRL 0x1CDE | |
69 | #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE | |
70 | #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE | |
71 | #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE | |
72 | #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE | |
73 | #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE | |
74 | #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE | |
75 | #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE | |
76 | #endif | |
77 | ||
78 | ||
79 | #ifndef mmBIOS_SCRATCH_2 | |
80 | #define mmBIOS_SCRATCH_2 0x05CB | |
c69dffab | 81 | #define mmBIOS_SCRATCH_3 0x05CC |
4562236b HW |
82 | #define mmBIOS_SCRATCH_6 0x05CF |
83 | #endif | |
84 | ||
85 | #ifndef mmDP_DPHY_FAST_TRAINING | |
86 | #define mmDP_DPHY_FAST_TRAINING 0x1CCE | |
87 | #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE | |
88 | #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE | |
89 | #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE | |
90 | #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE | |
91 | #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE | |
92 | #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE | |
93 | #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE | |
94 | #endif | |
95 | ||
96 | ||
97 | #ifndef mmHPD_DC_HPD_CONTROL | |
98 | #define mmHPD_DC_HPD_CONTROL 0x189A | |
99 | #define mmHPD0_DC_HPD_CONTROL 0x189A | |
100 | #define mmHPD1_DC_HPD_CONTROL 0x18A2 | |
101 | #define mmHPD2_DC_HPD_CONTROL 0x18AA | |
102 | #define mmHPD3_DC_HPD_CONTROL 0x18B2 | |
103 | #define mmHPD4_DC_HPD_CONTROL 0x18BA | |
104 | #define mmHPD5_DC_HPD_CONTROL 0x18C2 | |
105 | #endif | |
106 | ||
107 | #define DCE11_DIG_FE_CNTL 0x4a00 | |
108 | #define DCE11_DIG_BE_CNTL 0x4a47 | |
109 | #define DCE11_DP_SEC 0x4ac3 | |
110 | ||
111 | static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = { | |
112 | { | |
113 | .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), | |
114 | .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), | |
115 | .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL | |
116 | - mmDPG_WATERMARK_MASK_CONTROL), | |
117 | }, | |
118 | { | |
119 | .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), | |
120 | .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), | |
121 | .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL | |
122 | - mmDPG_WATERMARK_MASK_CONTROL), | |
123 | }, | |
124 | { | |
125 | .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), | |
126 | .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), | |
127 | .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL | |
128 | - mmDPG_WATERMARK_MASK_CONTROL), | |
129 | }, | |
130 | { | |
131 | .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), | |
132 | .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), | |
133 | .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL | |
134 | - mmDPG_WATERMARK_MASK_CONTROL), | |
135 | }, | |
136 | { | |
137 | .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), | |
138 | .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), | |
139 | .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL | |
140 | - mmDPG_WATERMARK_MASK_CONTROL), | |
141 | }, | |
142 | { | |
143 | .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), | |
144 | .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), | |
145 | .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL | |
146 | - mmDPG_WATERMARK_MASK_CONTROL), | |
147 | } | |
148 | }; | |
149 | ||
4562236b HW |
150 | /* set register offset */ |
151 | #define SR(reg_name)\ | |
152 | .reg_name = mm ## reg_name | |
153 | ||
154 | /* set register offset with instance */ | |
155 | #define SRI(reg_name, block, id)\ | |
156 | .reg_name = mm ## block ## id ## _ ## reg_name | |
157 | ||
e6303950 DL |
158 | #define ipp_regs(id)\ |
159 | [id] = {\ | |
160 | IPP_COMMON_REG_LIST_DCE_BASE(id)\ | |
161 | } | |
162 | ||
163 | static const struct dce_ipp_registers ipp_regs[] = { | |
164 | ipp_regs(0), | |
165 | ipp_regs(1), | |
166 | ipp_regs(2), | |
167 | ipp_regs(3), | |
168 | ipp_regs(4), | |
169 | ipp_regs(5) | |
170 | }; | |
171 | ||
172 | static const struct dce_ipp_shift ipp_shift = { | |
173 | IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) | |
174 | }; | |
175 | ||
176 | static const struct dce_ipp_mask ipp_mask = { | |
177 | IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) | |
178 | }; | |
179 | ||
4562236b HW |
180 | #define transform_regs(id)\ |
181 | [id] = {\ | |
513b5693 | 182 | XFM_COMMON_REG_LIST_DCE80(id)\ |
4562236b HW |
183 | } |
184 | ||
185 | static const struct dce_transform_registers xfm_regs[] = { | |
186 | transform_regs(0), | |
187 | transform_regs(1), | |
188 | transform_regs(2), | |
189 | transform_regs(3), | |
190 | transform_regs(4), | |
191 | transform_regs(5) | |
192 | }; | |
193 | ||
194 | static const struct dce_transform_shift xfm_shift = { | |
513b5693 | 195 | XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) |
4562236b HW |
196 | }; |
197 | ||
198 | static const struct dce_transform_mask xfm_mask = { | |
513b5693 | 199 | XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) |
4562236b HW |
200 | }; |
201 | ||
202 | #define aux_regs(id)\ | |
203 | [id] = {\ | |
204 | AUX_REG_LIST(id)\ | |
205 | } | |
206 | ||
207 | static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { | |
208 | aux_regs(0), | |
209 | aux_regs(1), | |
210 | aux_regs(2), | |
211 | aux_regs(3), | |
212 | aux_regs(4), | |
213 | aux_regs(5) | |
214 | }; | |
215 | ||
216 | #define hpd_regs(id)\ | |
217 | [id] = {\ | |
218 | HPD_REG_LIST(id)\ | |
219 | } | |
220 | ||
221 | static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { | |
222 | hpd_regs(0), | |
223 | hpd_regs(1), | |
224 | hpd_regs(2), | |
225 | hpd_regs(3), | |
226 | hpd_regs(4), | |
227 | hpd_regs(5) | |
228 | }; | |
229 | ||
230 | #define link_regs(id)\ | |
231 | [id] = {\ | |
232 | LE_DCE80_REG_LIST(id)\ | |
233 | } | |
234 | ||
235 | static const struct dce110_link_enc_registers link_enc_regs[] = { | |
236 | link_regs(0), | |
237 | link_regs(1), | |
238 | link_regs(2), | |
239 | link_regs(3), | |
240 | link_regs(4), | |
241 | link_regs(5), | |
242 | link_regs(6), | |
243 | }; | |
244 | ||
245 | #define stream_enc_regs(id)\ | |
246 | [id] = {\ | |
247 | SE_COMMON_REG_LIST_DCE_BASE(id),\ | |
248 | .AFMT_CNTL = 0,\ | |
249 | } | |
250 | ||
251 | static const struct dce110_stream_enc_registers stream_enc_regs[] = { | |
252 | stream_enc_regs(0), | |
253 | stream_enc_regs(1), | |
254 | stream_enc_regs(2), | |
255 | stream_enc_regs(3), | |
256 | stream_enc_regs(4), | |
ea062558 AD |
257 | stream_enc_regs(5), |
258 | stream_enc_regs(6) | |
4562236b HW |
259 | }; |
260 | ||
261 | static const struct dce_stream_encoder_shift se_shift = { | |
262 | SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) | |
263 | }; | |
264 | ||
265 | static const struct dce_stream_encoder_mask se_mask = { | |
266 | SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) | |
267 | }; | |
268 | ||
ab3ee7a5 ZF |
269 | #define opp_regs(id)\ |
270 | [id] = {\ | |
271 | OPP_DCE_80_REG_LIST(id),\ | |
272 | } | |
273 | ||
274 | static const struct dce_opp_registers opp_regs[] = { | |
275 | opp_regs(0), | |
276 | opp_regs(1), | |
277 | opp_regs(2), | |
278 | opp_regs(3), | |
279 | opp_regs(4), | |
280 | opp_regs(5) | |
281 | }; | |
282 | ||
283 | static const struct dce_opp_shift opp_shift = { | |
284 | OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) | |
285 | }; | |
286 | ||
287 | static const struct dce_opp_mask opp_mask = { | |
288 | OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) | |
289 | }; | |
290 | ||
5c6ac711 BL |
291 | #define aux_engine_regs(id)\ |
292 | [id] = {\ | |
293 | AUX_COMMON_REG_LIST(id), \ | |
294 | .AUX_RESET_MASK = 0 \ | |
295 | } | |
296 | ||
297 | static const struct dce110_aux_registers aux_engine_regs[] = { | |
298 | aux_engine_regs(0), | |
299 | aux_engine_regs(1), | |
300 | aux_engine_regs(2), | |
301 | aux_engine_regs(3), | |
302 | aux_engine_regs(4), | |
303 | aux_engine_regs(5) | |
304 | }; | |
305 | ||
4562236b HW |
306 | #define audio_regs(id)\ |
307 | [id] = {\ | |
308 | AUD_COMMON_REG_LIST(id)\ | |
309 | } | |
310 | ||
311 | static const struct dce_audio_registers audio_regs[] = { | |
312 | audio_regs(0), | |
313 | audio_regs(1), | |
314 | audio_regs(2), | |
315 | audio_regs(3), | |
316 | audio_regs(4), | |
317 | audio_regs(5), | |
318 | audio_regs(6), | |
319 | }; | |
320 | ||
321 | static const struct dce_audio_shift audio_shift = { | |
322 | AUD_COMMON_MASK_SH_LIST(__SHIFT) | |
323 | }; | |
324 | ||
54a9bcb0 | 325 | static const struct dce_audio_mask audio_mask = { |
4562236b HW |
326 | AUD_COMMON_MASK_SH_LIST(_MASK) |
327 | }; | |
328 | ||
329 | #define clk_src_regs(id)\ | |
330 | [id] = {\ | |
331 | CS_COMMON_REG_LIST_DCE_80(id),\ | |
332 | } | |
333 | ||
334 | ||
335 | static const struct dce110_clk_src_regs clk_src_regs[] = { | |
336 | clk_src_regs(0), | |
337 | clk_src_regs(1), | |
338 | clk_src_regs(2) | |
339 | }; | |
340 | ||
341 | static const struct dce110_clk_src_shift cs_shift = { | |
342 | CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) | |
343 | }; | |
344 | ||
345 | static const struct dce110_clk_src_mask cs_mask = { | |
346 | CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) | |
347 | }; | |
348 | ||
349 | static const struct bios_registers bios_regs = { | |
c69dffab | 350 | .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, |
4562236b HW |
351 | .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 |
352 | }; | |
353 | ||
354 | static const struct resource_caps res_cap = { | |
355 | .num_timing_generator = 6, | |
356 | .num_audio = 6, | |
357 | .num_stream_encoder = 6, | |
358 | .num_pll = 3, | |
0e8e4fbf | 359 | .num_ddc = 6, |
4562236b HW |
360 | }; |
361 | ||
7992a629 AD |
362 | static const struct resource_caps res_cap_81 = { |
363 | .num_timing_generator = 4, | |
364 | .num_audio = 7, | |
365 | .num_stream_encoder = 7, | |
366 | .num_pll = 3, | |
0e8e4fbf | 367 | .num_ddc = 6, |
7992a629 AD |
368 | }; |
369 | ||
370 | static const struct resource_caps res_cap_83 = { | |
371 | .num_timing_generator = 2, | |
372 | .num_audio = 6, | |
373 | .num_stream_encoder = 6, | |
374 | .num_pll = 2, | |
0e8e4fbf | 375 | .num_ddc = 2, |
7992a629 AD |
376 | }; |
377 | ||
e5c41970 NK |
378 | static const struct dc_plane_cap plane_cap = { |
379 | .type = DC_PLANE_TYPE_DCE_RGB, | |
ea36ad34 JL |
380 | |
381 | .pixel_format_support = { | |
382 | .argb8888 = true, | |
383 | .nv12 = false, | |
384 | .fp16 = false | |
385 | }, | |
386 | ||
387 | .max_upscale_factor = { | |
388 | .argb8888 = 16000, | |
389 | .nv12 = 1, | |
390 | .fp16 = 1 | |
391 | }, | |
392 | ||
393 | .max_downscale_factor = { | |
394 | .argb8888 = 250, | |
395 | .nv12 = 1, | |
396 | .fp16 = 1 | |
397 | } | |
e5c41970 NK |
398 | }; |
399 | ||
d54ee946 ML |
400 | static const struct dce_dmcu_registers dmcu_regs = { |
401 | DMCU_DCE80_REG_LIST() | |
402 | }; | |
403 | ||
404 | static const struct dce_dmcu_shift dmcu_shift = { | |
405 | DMCU_MASK_SH_LIST_DCE80(__SHIFT) | |
406 | }; | |
407 | ||
408 | static const struct dce_dmcu_mask dmcu_mask = { | |
409 | DMCU_MASK_SH_LIST_DCE80(_MASK) | |
410 | }; | |
411 | static const struct dce_abm_registers abm_regs = { | |
412 | ABM_DCE110_COMMON_REG_LIST() | |
413 | }; | |
414 | ||
415 | static const struct dce_abm_shift abm_shift = { | |
416 | ABM_MASK_SH_LIST_DCE110(__SHIFT) | |
417 | }; | |
418 | ||
419 | static const struct dce_abm_mask abm_mask = { | |
420 | ABM_MASK_SH_LIST_DCE110(_MASK) | |
421 | }; | |
422 | ||
4562236b HW |
423 | #define CTX ctx |
424 | #define REG(reg) mm ## reg | |
425 | ||
426 | #ifndef mmCC_DC_HDMI_STRAPS | |
427 | #define mmCC_DC_HDMI_STRAPS 0x1918 | |
428 | #define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 | |
429 | #define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 | |
430 | #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 | |
431 | #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 | |
432 | #endif | |
433 | ||
434 | static void read_dce_straps( | |
435 | struct dc_context *ctx, | |
436 | struct resource_straps *straps) | |
437 | { | |
438 | REG_GET_2(CC_DC_HDMI_STRAPS, | |
439 | HDMI_DISABLE, &straps->hdmi_disable, | |
440 | AUDIO_STREAM_NUMBER, &straps->audio_stream_number); | |
441 | ||
442 | REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); | |
443 | } | |
444 | ||
445 | static struct audio *create_audio( | |
446 | struct dc_context *ctx, unsigned int inst) | |
447 | { | |
448 | return dce_audio_create(ctx, inst, | |
449 | &audio_regs[inst], &audio_shift, &audio_mask); | |
450 | } | |
451 | ||
452 | static struct timing_generator *dce80_timing_generator_create( | |
453 | struct dc_context *ctx, | |
454 | uint32_t instance, | |
455 | const struct dce110_timing_generator_offsets *offsets) | |
456 | { | |
457 | struct dce110_timing_generator *tg110 = | |
2004f45e | 458 | kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); |
4562236b HW |
459 | |
460 | if (!tg110) | |
461 | return NULL; | |
462 | ||
99913a17 DA |
463 | dce80_timing_generator_construct(tg110, ctx, instance, offsets); |
464 | return &tg110->base; | |
4562236b HW |
465 | } |
466 | ||
ab3ee7a5 ZF |
467 | static struct output_pixel_processor *dce80_opp_create( |
468 | struct dc_context *ctx, | |
469 | uint32_t inst) | |
470 | { | |
471 | struct dce110_opp *opp = | |
2004f45e | 472 | kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); |
ab3ee7a5 ZF |
473 | |
474 | if (!opp) | |
475 | return NULL; | |
476 | ||
9cf29399 DA |
477 | dce110_opp_construct(opp, |
478 | ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); | |
479 | return &opp->base; | |
ab3ee7a5 ZF |
480 | } |
481 | ||
1877ccf6 | 482 | struct dce_aux *dce80_aux_engine_create( |
5c6ac711 BL |
483 | struct dc_context *ctx, |
484 | uint32_t inst) | |
485 | { | |
486 | struct aux_engine_dce110 *aux_engine = | |
487 | kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); | |
488 | ||
489 | if (!aux_engine) | |
490 | return NULL; | |
491 | ||
492 | dce110_aux_engine_construct(aux_engine, ctx, inst, | |
493 | SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, | |
494 | &aux_engine_regs[inst]); | |
495 | ||
65c78961 | 496 | return &aux_engine->base; |
5c6ac711 | 497 | } |
c85e6e54 DF |
498 | #define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } |
499 | ||
500 | static const struct dce_i2c_registers i2c_hw_regs[] = { | |
501 | i2c_inst_regs(1), | |
502 | i2c_inst_regs(2), | |
503 | i2c_inst_regs(3), | |
504 | i2c_inst_regs(4), | |
505 | i2c_inst_regs(5), | |
506 | i2c_inst_regs(6), | |
507 | }; | |
508 | ||
509 | static const struct dce_i2c_shift i2c_shifts = { | |
510 | I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) | |
511 | }; | |
512 | ||
513 | static const struct dce_i2c_mask i2c_masks = { | |
514 | I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) | |
515 | }; | |
516 | ||
517 | struct dce_i2c_hw *dce80_i2c_hw_create( | |
518 | struct dc_context *ctx, | |
519 | uint32_t inst) | |
520 | { | |
521 | struct dce_i2c_hw *dce_i2c_hw = | |
522 | kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); | |
523 | ||
524 | if (!dce_i2c_hw) | |
525 | return NULL; | |
526 | ||
527 | dce_i2c_hw_construct(dce_i2c_hw, ctx, inst, | |
528 | &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); | |
5c6ac711 | 529 | |
c85e6e54 DF |
530 | return dce_i2c_hw; |
531 | } | |
532 | ||
533 | struct dce_i2c_sw *dce80_i2c_sw_create( | |
534 | struct dc_context *ctx) | |
535 | { | |
536 | struct dce_i2c_sw *dce_i2c_sw = | |
537 | kzalloc(sizeof(struct dce_i2c_sw), GFP_KERNEL); | |
538 | ||
539 | if (!dce_i2c_sw) | |
540 | return NULL; | |
541 | ||
542 | dce_i2c_sw_construct(dce_i2c_sw, ctx); | |
543 | ||
544 | return dce_i2c_sw; | |
545 | } | |
4562236b HW |
546 | static struct stream_encoder *dce80_stream_encoder_create( |
547 | enum engine_id eng_id, | |
548 | struct dc_context *ctx) | |
549 | { | |
550 | struct dce110_stream_encoder *enc110 = | |
2004f45e | 551 | kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); |
4562236b HW |
552 | |
553 | if (!enc110) | |
554 | return NULL; | |
555 | ||
f29f918f DA |
556 | dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, |
557 | &stream_enc_regs[eng_id], | |
558 | &se_shift, &se_mask); | |
559 | return &enc110->base; | |
4562236b HW |
560 | } |
561 | ||
562 | #define SRII(reg_name, block, id)\ | |
563 | .reg_name[id] = mm ## block ## id ## _ ## reg_name | |
564 | ||
565 | static const struct dce_hwseq_registers hwseq_reg = { | |
566 | HWSEQ_DCE8_REG_LIST() | |
567 | }; | |
568 | ||
569 | static const struct dce_hwseq_shift hwseq_shift = { | |
570 | HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) | |
571 | }; | |
572 | ||
573 | static const struct dce_hwseq_mask hwseq_mask = { | |
574 | HWSEQ_DCE8_MASK_SH_LIST(_MASK) | |
575 | }; | |
576 | ||
577 | static struct dce_hwseq *dce80_hwseq_create( | |
578 | struct dc_context *ctx) | |
579 | { | |
2004f45e | 580 | struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); |
4562236b HW |
581 | |
582 | if (hws) { | |
583 | hws->ctx = ctx; | |
584 | hws->regs = &hwseq_reg; | |
585 | hws->shifts = &hwseq_shift; | |
586 | hws->masks = &hwseq_mask; | |
587 | } | |
588 | return hws; | |
589 | } | |
590 | ||
591 | static const struct resource_create_funcs res_create_funcs = { | |
592 | .read_dce_straps = read_dce_straps, | |
593 | .create_audio = create_audio, | |
594 | .create_stream_encoder = dce80_stream_encoder_create, | |
595 | .create_hwseq = dce80_hwseq_create, | |
596 | }; | |
597 | ||
598 | #define mi_inst_regs(id) { \ | |
197062bf | 599 | MI_DCE8_REG_LIST(id), \ |
4562236b HW |
600 | .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ |
601 | } | |
602 | static const struct dce_mem_input_registers mi_regs[] = { | |
603 | mi_inst_regs(0), | |
604 | mi_inst_regs(1), | |
605 | mi_inst_regs(2), | |
606 | mi_inst_regs(3), | |
607 | mi_inst_regs(4), | |
608 | mi_inst_regs(5), | |
609 | }; | |
610 | ||
611 | static const struct dce_mem_input_shift mi_shifts = { | |
197062bf | 612 | MI_DCE8_MASK_SH_LIST(__SHIFT), |
4562236b HW |
613 | .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT |
614 | }; | |
615 | ||
616 | static const struct dce_mem_input_mask mi_masks = { | |
197062bf | 617 | MI_DCE8_MASK_SH_LIST(_MASK), |
4562236b HW |
618 | .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK |
619 | }; | |
620 | ||
621 | static struct mem_input *dce80_mem_input_create( | |
622 | struct dc_context *ctx, | |
c3489214 | 623 | uint32_t inst) |
4562236b | 624 | { |
2004f45e HW |
625 | struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), |
626 | GFP_KERNEL); | |
4562236b | 627 | |
c3489214 DL |
628 | if (!dce_mi) { |
629 | BREAK_TO_DEBUGGER(); | |
4562236b | 630 | return NULL; |
4562236b HW |
631 | } |
632 | ||
c3489214 DL |
633 | dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); |
634 | dce_mi->wa.single_head_rdreq_dmif_limit = 2; | |
635 | return &dce_mi->base; | |
4562236b HW |
636 | } |
637 | ||
638 | static void dce80_transform_destroy(struct transform **xfm) | |
639 | { | |
2004f45e | 640 | kfree(TO_DCE_TRANSFORM(*xfm)); |
4562236b HW |
641 | *xfm = NULL; |
642 | } | |
643 | ||
644 | static struct transform *dce80_transform_create( | |
645 | struct dc_context *ctx, | |
646 | uint32_t inst) | |
647 | { | |
648 | struct dce_transform *transform = | |
2004f45e | 649 | kzalloc(sizeof(struct dce_transform), GFP_KERNEL); |
4562236b HW |
650 | |
651 | if (!transform) | |
652 | return NULL; | |
653 | ||
5fb005c4 DA |
654 | dce_transform_construct(transform, ctx, inst, |
655 | &xfm_regs[inst], &xfm_shift, &xfm_mask); | |
656 | transform->prescaler_on = false; | |
657 | return &transform->base; | |
4562236b HW |
658 | } |
659 | ||
7fc698a0 TC |
660 | static const struct encoder_feature_support link_enc_feature = { |
661 | .max_hdmi_deep_color = COLOR_DEPTH_121212, | |
662 | .max_hdmi_pixel_clock = 297000, | |
663 | .flags.bits.IS_HBR2_CAPABLE = true, | |
e15fc81f | 664 | .flags.bits.IS_TPS3_CAPABLE = true |
7fc698a0 TC |
665 | }; |
666 | ||
4562236b HW |
667 | struct link_encoder *dce80_link_encoder_create( |
668 | const struct encoder_init_data *enc_init_data) | |
669 | { | |
670 | struct dce110_link_encoder *enc110 = | |
2004f45e | 671 | kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); |
4562236b HW |
672 | |
673 | if (!enc110) | |
674 | return NULL; | |
675 | ||
c60ae112 DA |
676 | dce110_link_encoder_construct(enc110, |
677 | enc_init_data, | |
678 | &link_enc_feature, | |
679 | &link_enc_regs[enc_init_data->transmitter], | |
680 | &link_enc_aux_regs[enc_init_data->channel - 1], | |
681 | &link_enc_hpd_regs[enc_init_data->hpd_source]); | |
682 | return &enc110->base; | |
4562236b HW |
683 | } |
684 | ||
685 | struct clock_source *dce80_clock_source_create( | |
686 | struct dc_context *ctx, | |
687 | struct dc_bios *bios, | |
688 | enum clock_source_id id, | |
689 | const struct dce110_clk_src_regs *regs, | |
690 | bool dp_clk_src) | |
691 | { | |
692 | struct dce110_clk_src *clk_src = | |
2004f45e | 693 | kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); |
4562236b HW |
694 | |
695 | if (!clk_src) | |
696 | return NULL; | |
697 | ||
698 | if (dce110_clk_src_construct(clk_src, ctx, bios, id, | |
699 | regs, &cs_shift, &cs_mask)) { | |
700 | clk_src->base.dp_clk_src = dp_clk_src; | |
701 | return &clk_src->base; | |
702 | } | |
703 | ||
055e5474 | 704 | kfree(clk_src); |
4562236b HW |
705 | BREAK_TO_DEBUGGER(); |
706 | return NULL; | |
707 | } | |
708 | ||
709 | void dce80_clock_source_destroy(struct clock_source **clk_src) | |
710 | { | |
2004f45e | 711 | kfree(TO_DCE110_CLK_SRC(*clk_src)); |
4562236b HW |
712 | *clk_src = NULL; |
713 | } | |
714 | ||
e6303950 DL |
715 | static struct input_pixel_processor *dce80_ipp_create( |
716 | struct dc_context *ctx, uint32_t inst) | |
717 | { | |
2004f45e | 718 | struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); |
e6303950 DL |
719 | |
720 | if (!ipp) { | |
721 | BREAK_TO_DEBUGGER(); | |
722 | return NULL; | |
723 | } | |
724 | ||
725 | dce_ipp_construct(ipp, ctx, inst, | |
726 | &ipp_regs[inst], &ipp_shift, &ipp_mask); | |
727 | return &ipp->base; | |
728 | } | |
729 | ||
4562236b HW |
730 | static void destruct(struct dce110_resource_pool *pool) |
731 | { | |
732 | unsigned int i; | |
733 | ||
734 | for (i = 0; i < pool->base.pipe_count; i++) { | |
735 | if (pool->base.opps[i] != NULL) | |
ab3ee7a5 | 736 | dce110_opp_destroy(&pool->base.opps[i]); |
4562236b HW |
737 | |
738 | if (pool->base.transforms[i] != NULL) | |
739 | dce80_transform_destroy(&pool->base.transforms[i]); | |
740 | ||
741 | if (pool->base.ipps[i] != NULL) | |
e6303950 | 742 | dce_ipp_destroy(&pool->base.ipps[i]); |
4562236b HW |
743 | |
744 | if (pool->base.mis[i] != NULL) { | |
2004f45e | 745 | kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); |
4562236b HW |
746 | pool->base.mis[i] = NULL; |
747 | } | |
748 | ||
749 | if (pool->base.timing_generators[i] != NULL) { | |
2004f45e | 750 | kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); |
4562236b HW |
751 | pool->base.timing_generators[i] = NULL; |
752 | } | |
88ed9fb7 | 753 | } |
5c6ac711 | 754 | |
88ed9fb7 | 755 | for (i = 0; i < pool->base.res_cap->num_ddc; i++) { |
5c6ac711 BL |
756 | if (pool->base.engines[i] != NULL) |
757 | dce110_engine_destroy(&pool->base.engines[i]); | |
c85e6e54 DF |
758 | if (pool->base.hw_i2cs[i] != NULL) { |
759 | kfree(pool->base.hw_i2cs[i]); | |
760 | pool->base.hw_i2cs[i] = NULL; | |
761 | } | |
762 | if (pool->base.sw_i2cs[i] != NULL) { | |
763 | kfree(pool->base.sw_i2cs[i]); | |
764 | pool->base.sw_i2cs[i] = NULL; | |
765 | } | |
4562236b HW |
766 | } |
767 | ||
768 | for (i = 0; i < pool->base.stream_enc_count; i++) { | |
769 | if (pool->base.stream_enc[i] != NULL) | |
2004f45e | 770 | kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); |
4562236b HW |
771 | } |
772 | ||
773 | for (i = 0; i < pool->base.clk_src_count; i++) { | |
774 | if (pool->base.clock_sources[i] != NULL) { | |
775 | dce80_clock_source_destroy(&pool->base.clock_sources[i]); | |
776 | } | |
777 | } | |
778 | ||
d54ee946 ML |
779 | if (pool->base.abm != NULL) |
780 | dce_abm_destroy(&pool->base.abm); | |
781 | ||
782 | if (pool->base.dmcu != NULL) | |
783 | dce_dmcu_destroy(&pool->base.dmcu); | |
784 | ||
4562236b HW |
785 | if (pool->base.dp_clock_source != NULL) |
786 | dce80_clock_source_destroy(&pool->base.dp_clock_source); | |
787 | ||
788 | for (i = 0; i < pool->base.audio_count; i++) { | |
789 | if (pool->base.audios[i] != NULL) { | |
790 | dce_aud_destroy(&pool->base.audios[i]); | |
791 | } | |
792 | } | |
793 | ||
4562236b HW |
794 | if (pool->base.irqs != NULL) { |
795 | dal_irq_service_destroy(&pool->base.irqs); | |
796 | } | |
797 | } | |
798 | ||
45209ef7 | 799 | bool dce80_validate_bandwidth( |
fb3466a4 | 800 | struct dc *dc, |
afcd526b JA |
801 | struct dc_state *context, |
802 | bool fast_validate) | |
4562236b | 803 | { |
4ece61a2 BL |
804 | int i; |
805 | bool at_least_one_pipe = false; | |
806 | ||
807 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
808 | if (context->res_ctx.pipe_ctx[i].stream) | |
809 | at_least_one_pipe = true; | |
810 | } | |
811 | ||
812 | if (at_least_one_pipe) { | |
813 | /* TODO implement when needed but for now hardcode max value*/ | |
813d20dc AW |
814 | context->bw_ctx.bw.dce.dispclk_khz = 681000; |
815 | context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; | |
4ece61a2 | 816 | } else { |
813d20dc AW |
817 | context->bw_ctx.bw.dce.dispclk_khz = 0; |
818 | context->bw_ctx.bw.dce.yclk_khz = 0; | |
4ece61a2 | 819 | } |
4562236b | 820 | |
45209ef7 | 821 | return true; |
4562236b HW |
822 | } |
823 | ||
824 | static bool dce80_validate_surface_sets( | |
608ac7bb | 825 | struct dc_state *context) |
4562236b HW |
826 | { |
827 | int i; | |
828 | ||
19f89e23 AG |
829 | for (i = 0; i < context->stream_count; i++) { |
830 | if (context->stream_status[i].plane_count == 0) | |
4562236b HW |
831 | continue; |
832 | ||
19f89e23 | 833 | if (context->stream_status[i].plane_count > 1) |
4562236b HW |
834 | return false; |
835 | ||
19f89e23 | 836 | if (context->stream_status[i].plane_states[0]->format |
4562236b HW |
837 | >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) |
838 | return false; | |
839 | } | |
840 | ||
841 | return true; | |
842 | } | |
843 | ||
1dc90497 | 844 | enum dc_status dce80_validate_global( |
fb3466a4 | 845 | struct dc *dc, |
608ac7bb | 846 | struct dc_state *context) |
4562236b | 847 | { |
19f89e23 | 848 | if (!dce80_validate_surface_sets(context)) |
4562236b HW |
849 | return DC_FAIL_SURFACE_VALIDATE; |
850 | ||
1dc90497 | 851 | return DC_OK; |
4562236b HW |
852 | } |
853 | ||
4562236b HW |
854 | static void dce80_destroy_resource_pool(struct resource_pool **pool) |
855 | { | |
856 | struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); | |
857 | ||
858 | destruct(dce110_pool); | |
2004f45e | 859 | kfree(dce110_pool); |
4562236b HW |
860 | *pool = NULL; |
861 | } | |
862 | ||
863 | static const struct resource_funcs dce80_res_pool_funcs = { | |
864 | .destroy = dce80_destroy_resource_pool, | |
865 | .link_enc_create = dce80_link_encoder_create, | |
792671d7 | 866 | .validate_bandwidth = dce80_validate_bandwidth, |
1dc90497 | 867 | .validate_plane = dce100_validate_plane, |
1d9521a7 | 868 | .add_stream_to_ctx = dce100_add_stream_to_ctx, |
78cc70b1 WC |
869 | .validate_global = dce80_validate_global, |
870 | .find_first_free_match_stream_enc_for_link = dce100_find_first_free_match_stream_enc_for_link | |
4562236b HW |
871 | }; |
872 | ||
7992a629 | 873 | static bool dce80_construct( |
4562236b | 874 | uint8_t num_virtual_links, |
fb3466a4 | 875 | struct dc *dc, |
4562236b HW |
876 | struct dce110_resource_pool *pool) |
877 | { | |
878 | unsigned int i; | |
879 | struct dc_context *ctx = dc->ctx; | |
4562236b | 880 | struct dc_bios *bp; |
4562236b HW |
881 | |
882 | ctx->dc_bios->regs = &bios_regs; | |
883 | ||
884 | pool->base.res_cap = &res_cap; | |
885 | pool->base.funcs = &dce80_res_pool_funcs; | |
886 | ||
887 | ||
888 | /************************************************* | |
889 | * Resource + asic cap harcoding * | |
890 | *************************************************/ | |
f0e3db90 | 891 | pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; |
4562236b | 892 | pool->base.pipe_count = res_cap.num_timing_generator; |
3be1406a | 893 | pool->base.timing_generator_count = res_cap.num_timing_generator; |
fb3466a4 BL |
894 | dc->caps.max_downscale_ratio = 200; |
895 | dc->caps.i2c_speed_in_khz = 40; | |
896 | dc->caps.max_cursor_size = 128; | |
7e98ab10 | 897 | dc->caps.dual_link_dvi = true; |
4562236b HW |
898 | |
899 | /************************************************* | |
900 | * Create resources * | |
901 | *************************************************/ | |
902 | ||
903 | bp = ctx->dc_bios; | |
904 | ||
9adc8050 | 905 | if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { |
4562236b HW |
906 | pool->base.dp_clock_source = |
907 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); | |
908 | ||
909 | pool->base.clock_sources[0] = | |
910 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); | |
911 | pool->base.clock_sources[1] = | |
912 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); | |
913 | pool->base.clock_sources[2] = | |
914 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); | |
915 | pool->base.clk_src_count = 3; | |
916 | ||
917 | } else { | |
918 | pool->base.dp_clock_source = | |
919 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); | |
920 | ||
921 | pool->base.clock_sources[0] = | |
922 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); | |
923 | pool->base.clock_sources[1] = | |
924 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); | |
925 | pool->base.clk_src_count = 2; | |
926 | } | |
927 | ||
928 | if (pool->base.dp_clock_source == NULL) { | |
929 | dm_error("DC: failed to create dp clock source!\n"); | |
930 | BREAK_TO_DEBUGGER(); | |
931 | goto res_create_fail; | |
932 | } | |
933 | ||
934 | for (i = 0; i < pool->base.clk_src_count; i++) { | |
935 | if (pool->base.clock_sources[i] == NULL) { | |
936 | dm_error("DC: failed to create clock sources!\n"); | |
937 | BREAK_TO_DEBUGGER(); | |
938 | goto res_create_fail; | |
939 | } | |
940 | } | |
941 | ||
d54ee946 ML |
942 | pool->base.dmcu = dce_dmcu_create(ctx, |
943 | &dmcu_regs, | |
944 | &dmcu_shift, | |
945 | &dmcu_mask); | |
946 | if (pool->base.dmcu == NULL) { | |
947 | dm_error("DC: failed to create dmcu!\n"); | |
948 | BREAK_TO_DEBUGGER(); | |
949 | goto res_create_fail; | |
950 | } | |
4562236b | 951 | |
d54ee946 ML |
952 | pool->base.abm = dce_abm_create(ctx, |
953 | &abm_regs, | |
954 | &abm_shift, | |
955 | &abm_mask); | |
956 | if (pool->base.abm == NULL) { | |
957 | dm_error("DC: failed to create abm!\n"); | |
958 | BREAK_TO_DEBUGGER(); | |
959 | goto res_create_fail; | |
960 | } | |
c85e6e54 | 961 | |
4562236b HW |
962 | { |
963 | struct irq_service_init_data init_data; | |
964 | init_data.ctx = dc->ctx; | |
965 | pool->base.irqs = dal_irq_service_dce80_create(&init_data); | |
966 | if (!pool->base.irqs) | |
967 | goto res_create_fail; | |
968 | } | |
969 | ||
970 | for (i = 0; i < pool->base.pipe_count; i++) { | |
971 | pool->base.timing_generators[i] = dce80_timing_generator_create( | |
972 | ctx, i, &dce80_tg_offsets[i]); | |
973 | if (pool->base.timing_generators[i] == NULL) { | |
974 | BREAK_TO_DEBUGGER(); | |
975 | dm_error("DC: failed to create tg!\n"); | |
976 | goto res_create_fail; | |
977 | } | |
978 | ||
c3489214 | 979 | pool->base.mis[i] = dce80_mem_input_create(ctx, i); |
4562236b HW |
980 | if (pool->base.mis[i] == NULL) { |
981 | BREAK_TO_DEBUGGER(); | |
982 | dm_error("DC: failed to create memory input!\n"); | |
983 | goto res_create_fail; | |
984 | } | |
985 | ||
e6303950 | 986 | pool->base.ipps[i] = dce80_ipp_create(ctx, i); |
4562236b HW |
987 | if (pool->base.ipps[i] == NULL) { |
988 | BREAK_TO_DEBUGGER(); | |
989 | dm_error("DC: failed to create input pixel processor!\n"); | |
990 | goto res_create_fail; | |
991 | } | |
992 | ||
993 | pool->base.transforms[i] = dce80_transform_create(ctx, i); | |
994 | if (pool->base.transforms[i] == NULL) { | |
995 | BREAK_TO_DEBUGGER(); | |
996 | dm_error("DC: failed to create transform!\n"); | |
997 | goto res_create_fail; | |
998 | } | |
999 | ||
1000 | pool->base.opps[i] = dce80_opp_create(ctx, i); | |
1001 | if (pool->base.opps[i] == NULL) { | |
1002 | BREAK_TO_DEBUGGER(); | |
1003 | dm_error("DC: failed to create output pixel processor!\n"); | |
1004 | goto res_create_fail; | |
1005 | } | |
0e8e4fbf | 1006 | } |
5c6ac711 | 1007 | |
0e8e4fbf | 1008 | for (i = 0; i < pool->base.res_cap->num_ddc; i++) { |
5c6ac711 BL |
1009 | pool->base.engines[i] = dce80_aux_engine_create(ctx, i); |
1010 | if (pool->base.engines[i] == NULL) { | |
1011 | BREAK_TO_DEBUGGER(); | |
1012 | dm_error( | |
1013 | "DC:failed to create aux engine!!\n"); | |
1014 | goto res_create_fail; | |
1015 | } | |
c85e6e54 DF |
1016 | pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); |
1017 | if (pool->base.hw_i2cs[i] == NULL) { | |
1018 | BREAK_TO_DEBUGGER(); | |
1019 | dm_error( | |
1020 | "DC:failed to create i2c engine!!\n"); | |
1021 | goto res_create_fail; | |
1022 | } | |
1023 | pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); | |
1024 | if (pool->base.sw_i2cs[i] == NULL) { | |
1025 | BREAK_TO_DEBUGGER(); | |
1026 | dm_error( | |
1027 | "DC:failed to create sw i2c!!\n"); | |
1028 | goto res_create_fail; | |
1029 | } | |
4562236b HW |
1030 | } |
1031 | ||
fb3466a4 | 1032 | dc->caps.max_planes = pool->base.pipe_count; |
e5c41970 NK |
1033 | |
1034 | for (i = 0; i < dc->caps.max_planes; ++i) | |
1035 | dc->caps.planes[i] = plane_cap; | |
1036 | ||
3e27e10e | 1037 | dc->caps.disable_dp_clk_share = true; |
d4e13b0d | 1038 | |
4562236b HW |
1039 | if (!resource_construct(num_virtual_links, dc, &pool->base, |
1040 | &res_create_funcs)) | |
1041 | goto res_create_fail; | |
1042 | ||
1043 | /* Create hardware sequencer */ | |
c13b408b | 1044 | dce80_hw_sequencer_construct(dc); |
4562236b HW |
1045 | |
1046 | return true; | |
1047 | ||
1048 | res_create_fail: | |
1049 | destruct(pool); | |
1050 | return false; | |
1051 | } | |
1052 | ||
1053 | struct resource_pool *dce80_create_resource_pool( | |
1054 | uint8_t num_virtual_links, | |
fb3466a4 | 1055 | struct dc *dc) |
4562236b HW |
1056 | { |
1057 | struct dce110_resource_pool *pool = | |
2004f45e | 1058 | kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); |
4562236b HW |
1059 | |
1060 | if (!pool) | |
1061 | return NULL; | |
1062 | ||
7992a629 | 1063 | if (dce80_construct(num_virtual_links, dc, pool)) |
4562236b HW |
1064 | return &pool->base; |
1065 | ||
1066 | BREAK_TO_DEBUGGER(); | |
1067 | return NULL; | |
1068 | } | |
1069 | ||
7992a629 AD |
1070 | static bool dce81_construct( |
1071 | uint8_t num_virtual_links, | |
fb3466a4 | 1072 | struct dc *dc, |
7992a629 AD |
1073 | struct dce110_resource_pool *pool) |
1074 | { | |
1075 | unsigned int i; | |
1076 | struct dc_context *ctx = dc->ctx; | |
7992a629 | 1077 | struct dc_bios *bp; |
7992a629 AD |
1078 | |
1079 | ctx->dc_bios->regs = &bios_regs; | |
1080 | ||
1081 | pool->base.res_cap = &res_cap_81; | |
1082 | pool->base.funcs = &dce80_res_pool_funcs; | |
1083 | ||
1084 | ||
1085 | /************************************************* | |
1086 | * Resource + asic cap harcoding * | |
1087 | *************************************************/ | |
1088 | pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; | |
1089 | pool->base.pipe_count = res_cap_81.num_timing_generator; | |
3be1406a | 1090 | pool->base.timing_generator_count = res_cap_81.num_timing_generator; |
fb3466a4 BL |
1091 | dc->caps.max_downscale_ratio = 200; |
1092 | dc->caps.i2c_speed_in_khz = 40; | |
1093 | dc->caps.max_cursor_size = 128; | |
553aae12 | 1094 | dc->caps.is_apu = true; |
7992a629 AD |
1095 | |
1096 | /************************************************* | |
1097 | * Create resources * | |
1098 | *************************************************/ | |
1099 | ||
1100 | bp = ctx->dc_bios; | |
1101 | ||
9adc8050 | 1102 | if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { |
7992a629 AD |
1103 | pool->base.dp_clock_source = |
1104 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); | |
1105 | ||
1106 | pool->base.clock_sources[0] = | |
1107 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); | |
1108 | pool->base.clock_sources[1] = | |
1109 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); | |
1110 | pool->base.clock_sources[2] = | |
1111 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); | |
1112 | pool->base.clk_src_count = 3; | |
1113 | ||
1114 | } else { | |
1115 | pool->base.dp_clock_source = | |
1116 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); | |
1117 | ||
1118 | pool->base.clock_sources[0] = | |
1119 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); | |
1120 | pool->base.clock_sources[1] = | |
1121 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); | |
1122 | pool->base.clk_src_count = 2; | |
1123 | } | |
1124 | ||
1125 | if (pool->base.dp_clock_source == NULL) { | |
1126 | dm_error("DC: failed to create dp clock source!\n"); | |
1127 | BREAK_TO_DEBUGGER(); | |
1128 | goto res_create_fail; | |
1129 | } | |
1130 | ||
1131 | for (i = 0; i < pool->base.clk_src_count; i++) { | |
1132 | if (pool->base.clock_sources[i] == NULL) { | |
1133 | dm_error("DC: failed to create clock sources!\n"); | |
1134 | BREAK_TO_DEBUGGER(); | |
1135 | goto res_create_fail; | |
1136 | } | |
1137 | } | |
1138 | ||
d54ee946 ML |
1139 | pool->base.dmcu = dce_dmcu_create(ctx, |
1140 | &dmcu_regs, | |
1141 | &dmcu_shift, | |
1142 | &dmcu_mask); | |
1143 | if (pool->base.dmcu == NULL) { | |
1144 | dm_error("DC: failed to create dmcu!\n"); | |
1145 | BREAK_TO_DEBUGGER(); | |
1146 | goto res_create_fail; | |
1147 | } | |
1148 | ||
1149 | pool->base.abm = dce_abm_create(ctx, | |
1150 | &abm_regs, | |
1151 | &abm_shift, | |
1152 | &abm_mask); | |
1153 | if (pool->base.abm == NULL) { | |
1154 | dm_error("DC: failed to create abm!\n"); | |
1155 | BREAK_TO_DEBUGGER(); | |
1156 | goto res_create_fail; | |
1157 | } | |
7992a629 | 1158 | |
7992a629 AD |
1159 | { |
1160 | struct irq_service_init_data init_data; | |
1161 | init_data.ctx = dc->ctx; | |
1162 | pool->base.irqs = dal_irq_service_dce80_create(&init_data); | |
1163 | if (!pool->base.irqs) | |
1164 | goto res_create_fail; | |
1165 | } | |
1166 | ||
1167 | for (i = 0; i < pool->base.pipe_count; i++) { | |
1168 | pool->base.timing_generators[i] = dce80_timing_generator_create( | |
1169 | ctx, i, &dce80_tg_offsets[i]); | |
1170 | if (pool->base.timing_generators[i] == NULL) { | |
1171 | BREAK_TO_DEBUGGER(); | |
1172 | dm_error("DC: failed to create tg!\n"); | |
1173 | goto res_create_fail; | |
1174 | } | |
1175 | ||
1176 | pool->base.mis[i] = dce80_mem_input_create(ctx, i); | |
1177 | if (pool->base.mis[i] == NULL) { | |
1178 | BREAK_TO_DEBUGGER(); | |
1179 | dm_error("DC: failed to create memory input!\n"); | |
1180 | goto res_create_fail; | |
1181 | } | |
1182 | ||
1183 | pool->base.ipps[i] = dce80_ipp_create(ctx, i); | |
1184 | if (pool->base.ipps[i] == NULL) { | |
1185 | BREAK_TO_DEBUGGER(); | |
1186 | dm_error("DC: failed to create input pixel processor!\n"); | |
1187 | goto res_create_fail; | |
1188 | } | |
1189 | ||
1190 | pool->base.transforms[i] = dce80_transform_create(ctx, i); | |
1191 | if (pool->base.transforms[i] == NULL) { | |
1192 | BREAK_TO_DEBUGGER(); | |
1193 | dm_error("DC: failed to create transform!\n"); | |
1194 | goto res_create_fail; | |
1195 | } | |
1196 | ||
1197 | pool->base.opps[i] = dce80_opp_create(ctx, i); | |
1198 | if (pool->base.opps[i] == NULL) { | |
1199 | BREAK_TO_DEBUGGER(); | |
1200 | dm_error("DC: failed to create output pixel processor!\n"); | |
1201 | goto res_create_fail; | |
1202 | } | |
0e8e4fbf HW |
1203 | } |
1204 | ||
1205 | for (i = 0; i < pool->base.res_cap->num_ddc; i++) { | |
1206 | pool->base.engines[i] = dce80_aux_engine_create(ctx, i); | |
1207 | if (pool->base.engines[i] == NULL) { | |
1208 | BREAK_TO_DEBUGGER(); | |
1209 | dm_error( | |
1210 | "DC:failed to create aux engine!!\n"); | |
1211 | goto res_create_fail; | |
1212 | } | |
c85e6e54 DF |
1213 | pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); |
1214 | if (pool->base.hw_i2cs[i] == NULL) { | |
1215 | BREAK_TO_DEBUGGER(); | |
1216 | dm_error( | |
1217 | "DC:failed to create i2c engine!!\n"); | |
1218 | goto res_create_fail; | |
1219 | } | |
1220 | pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); | |
1221 | if (pool->base.sw_i2cs[i] == NULL) { | |
1222 | BREAK_TO_DEBUGGER(); | |
1223 | dm_error( | |
1224 | "DC:failed to create sw i2c!!\n"); | |
1225 | goto res_create_fail; | |
1226 | } | |
7992a629 AD |
1227 | } |
1228 | ||
fb3466a4 | 1229 | dc->caps.max_planes = pool->base.pipe_count; |
e5c41970 NK |
1230 | |
1231 | for (i = 0; i < dc->caps.max_planes; ++i) | |
1232 | dc->caps.planes[i] = plane_cap; | |
1233 | ||
3e27e10e | 1234 | dc->caps.disable_dp_clk_share = true; |
7992a629 AD |
1235 | |
1236 | if (!resource_construct(num_virtual_links, dc, &pool->base, | |
1237 | &res_create_funcs)) | |
1238 | goto res_create_fail; | |
1239 | ||
1240 | /* Create hardware sequencer */ | |
c13b408b | 1241 | dce80_hw_sequencer_construct(dc); |
7992a629 AD |
1242 | |
1243 | return true; | |
1244 | ||
1245 | res_create_fail: | |
1246 | destruct(pool); | |
1247 | return false; | |
1248 | } | |
1249 | ||
1250 | struct resource_pool *dce81_create_resource_pool( | |
1251 | uint8_t num_virtual_links, | |
fb3466a4 | 1252 | struct dc *dc) |
7992a629 AD |
1253 | { |
1254 | struct dce110_resource_pool *pool = | |
2004f45e | 1255 | kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); |
7992a629 AD |
1256 | |
1257 | if (!pool) | |
1258 | return NULL; | |
1259 | ||
1260 | if (dce81_construct(num_virtual_links, dc, pool)) | |
1261 | return &pool->base; | |
1262 | ||
1263 | BREAK_TO_DEBUGGER(); | |
1264 | return NULL; | |
1265 | } | |
1266 | ||
1267 | static bool dce83_construct( | |
1268 | uint8_t num_virtual_links, | |
fb3466a4 | 1269 | struct dc *dc, |
7992a629 AD |
1270 | struct dce110_resource_pool *pool) |
1271 | { | |
1272 | unsigned int i; | |
1273 | struct dc_context *ctx = dc->ctx; | |
7992a629 | 1274 | struct dc_bios *bp; |
7992a629 AD |
1275 | |
1276 | ctx->dc_bios->regs = &bios_regs; | |
1277 | ||
1278 | pool->base.res_cap = &res_cap_83; | |
1279 | pool->base.funcs = &dce80_res_pool_funcs; | |
1280 | ||
1281 | ||
1282 | /************************************************* | |
1283 | * Resource + asic cap harcoding * | |
1284 | *************************************************/ | |
1285 | pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; | |
1286 | pool->base.pipe_count = res_cap_83.num_timing_generator; | |
3be1406a | 1287 | pool->base.timing_generator_count = res_cap_83.num_timing_generator; |
fb3466a4 BL |
1288 | dc->caps.max_downscale_ratio = 200; |
1289 | dc->caps.i2c_speed_in_khz = 40; | |
1290 | dc->caps.max_cursor_size = 128; | |
553aae12 | 1291 | dc->caps.is_apu = true; |
7992a629 AD |
1292 | |
1293 | /************************************************* | |
1294 | * Create resources * | |
1295 | *************************************************/ | |
1296 | ||
1297 | bp = ctx->dc_bios; | |
1298 | ||
9adc8050 | 1299 | if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { |
7992a629 AD |
1300 | pool->base.dp_clock_source = |
1301 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); | |
1302 | ||
1303 | pool->base.clock_sources[0] = | |
1304 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); | |
1305 | pool->base.clock_sources[1] = | |
1306 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); | |
1307 | pool->base.clk_src_count = 2; | |
1308 | ||
1309 | } else { | |
1310 | pool->base.dp_clock_source = | |
1311 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); | |
1312 | ||
1313 | pool->base.clock_sources[0] = | |
1314 | dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); | |
1315 | pool->base.clk_src_count = 1; | |
1316 | } | |
1317 | ||
1318 | if (pool->base.dp_clock_source == NULL) { | |
1319 | dm_error("DC: failed to create dp clock source!\n"); | |
1320 | BREAK_TO_DEBUGGER(); | |
1321 | goto res_create_fail; | |
1322 | } | |
1323 | ||
1324 | for (i = 0; i < pool->base.clk_src_count; i++) { | |
1325 | if (pool->base.clock_sources[i] == NULL) { | |
1326 | dm_error("DC: failed to create clock sources!\n"); | |
1327 | BREAK_TO_DEBUGGER(); | |
1328 | goto res_create_fail; | |
1329 | } | |
1330 | } | |
1331 | ||
d54ee946 ML |
1332 | pool->base.dmcu = dce_dmcu_create(ctx, |
1333 | &dmcu_regs, | |
1334 | &dmcu_shift, | |
1335 | &dmcu_mask); | |
1336 | if (pool->base.dmcu == NULL) { | |
1337 | dm_error("DC: failed to create dmcu!\n"); | |
1338 | BREAK_TO_DEBUGGER(); | |
1339 | goto res_create_fail; | |
1340 | } | |
1341 | ||
1342 | pool->base.abm = dce_abm_create(ctx, | |
1343 | &abm_regs, | |
1344 | &abm_shift, | |
1345 | &abm_mask); | |
1346 | if (pool->base.abm == NULL) { | |
1347 | dm_error("DC: failed to create abm!\n"); | |
1348 | BREAK_TO_DEBUGGER(); | |
1349 | goto res_create_fail; | |
1350 | } | |
7992a629 | 1351 | |
7992a629 AD |
1352 | { |
1353 | struct irq_service_init_data init_data; | |
1354 | init_data.ctx = dc->ctx; | |
1355 | pool->base.irqs = dal_irq_service_dce80_create(&init_data); | |
1356 | if (!pool->base.irqs) | |
1357 | goto res_create_fail; | |
1358 | } | |
1359 | ||
1360 | for (i = 0; i < pool->base.pipe_count; i++) { | |
1361 | pool->base.timing_generators[i] = dce80_timing_generator_create( | |
1362 | ctx, i, &dce80_tg_offsets[i]); | |
1363 | if (pool->base.timing_generators[i] == NULL) { | |
1364 | BREAK_TO_DEBUGGER(); | |
1365 | dm_error("DC: failed to create tg!\n"); | |
1366 | goto res_create_fail; | |
1367 | } | |
1368 | ||
1369 | pool->base.mis[i] = dce80_mem_input_create(ctx, i); | |
1370 | if (pool->base.mis[i] == NULL) { | |
1371 | BREAK_TO_DEBUGGER(); | |
1372 | dm_error("DC: failed to create memory input!\n"); | |
1373 | goto res_create_fail; | |
1374 | } | |
1375 | ||
1376 | pool->base.ipps[i] = dce80_ipp_create(ctx, i); | |
1377 | if (pool->base.ipps[i] == NULL) { | |
1378 | BREAK_TO_DEBUGGER(); | |
1379 | dm_error("DC: failed to create input pixel processor!\n"); | |
1380 | goto res_create_fail; | |
1381 | } | |
1382 | ||
1383 | pool->base.transforms[i] = dce80_transform_create(ctx, i); | |
1384 | if (pool->base.transforms[i] == NULL) { | |
1385 | BREAK_TO_DEBUGGER(); | |
1386 | dm_error("DC: failed to create transform!\n"); | |
1387 | goto res_create_fail; | |
1388 | } | |
1389 | ||
1390 | pool->base.opps[i] = dce80_opp_create(ctx, i); | |
1391 | if (pool->base.opps[i] == NULL) { | |
1392 | BREAK_TO_DEBUGGER(); | |
1393 | dm_error("DC: failed to create output pixel processor!\n"); | |
1394 | goto res_create_fail; | |
1395 | } | |
0e8e4fbf HW |
1396 | } |
1397 | ||
1398 | for (i = 0; i < pool->base.res_cap->num_ddc; i++) { | |
1399 | pool->base.engines[i] = dce80_aux_engine_create(ctx, i); | |
1400 | if (pool->base.engines[i] == NULL) { | |
1401 | BREAK_TO_DEBUGGER(); | |
1402 | dm_error( | |
1403 | "DC:failed to create aux engine!!\n"); | |
1404 | goto res_create_fail; | |
1405 | } | |
c85e6e54 DF |
1406 | pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); |
1407 | if (pool->base.hw_i2cs[i] == NULL) { | |
1408 | BREAK_TO_DEBUGGER(); | |
1409 | dm_error( | |
1410 | "DC:failed to create i2c engine!!\n"); | |
1411 | goto res_create_fail; | |
1412 | } | |
1413 | pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); | |
1414 | if (pool->base.sw_i2cs[i] == NULL) { | |
1415 | BREAK_TO_DEBUGGER(); | |
1416 | dm_error( | |
1417 | "DC:failed to create sw i2c!!\n"); | |
1418 | goto res_create_fail; | |
1419 | } | |
7992a629 AD |
1420 | } |
1421 | ||
fb3466a4 | 1422 | dc->caps.max_planes = pool->base.pipe_count; |
e5c41970 NK |
1423 | |
1424 | for (i = 0; i < dc->caps.max_planes; ++i) | |
1425 | dc->caps.planes[i] = plane_cap; | |
1426 | ||
3e27e10e | 1427 | dc->caps.disable_dp_clk_share = true; |
7992a629 AD |
1428 | |
1429 | if (!resource_construct(num_virtual_links, dc, &pool->base, | |
1430 | &res_create_funcs)) | |
1431 | goto res_create_fail; | |
1432 | ||
1433 | /* Create hardware sequencer */ | |
c13b408b | 1434 | dce80_hw_sequencer_construct(dc); |
7992a629 AD |
1435 | |
1436 | return true; | |
1437 | ||
1438 | res_create_fail: | |
1439 | destruct(pool); | |
1440 | return false; | |
1441 | } | |
1442 | ||
1443 | struct resource_pool *dce83_create_resource_pool( | |
1444 | uint8_t num_virtual_links, | |
fb3466a4 | 1445 | struct dc *dc) |
7992a629 AD |
1446 | { |
1447 | struct dce110_resource_pool *pool = | |
2004f45e | 1448 | kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); |
7992a629 AD |
1449 | |
1450 | if (!pool) | |
1451 | return NULL; | |
1452 | ||
1453 | if (dce83_construct(num_virtual_links, dc, pool)) | |
1454 | return &pool->base; | |
1455 | ||
1456 | BREAK_TO_DEBUGGER(); | |
1457 | return NULL; | |
1458 | } |