]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
drm/amd/display: remove store clock state
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dce80 / dce80_resource.c
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
26 #include "dce/dce_8_0_d.h"
27 #include "dce/dce_8_0_sh_mask.h"
28
29 #include "dm_services.h"
30
31 #include "link_encoder.h"
32 #include "stream_encoder.h"
33
34 #include "resource.h"
35 #include "include/irq_service_interface.h"
36 #include "irq/dce80/irq_service_dce80.h"
37 #include "dce110/dce110_timing_generator.h"
38 #include "dce110/dce110_mem_input.h"
39 #include "dce110/dce110_resource.h"
40 #include "dce80/dce80_timing_generator.h"
41 #include "dce/dce_link_encoder.h"
42 #include "dce/dce_stream_encoder.h"
43 #include "dce80/dce80_mem_input.h"
44 #include "dce80/dce80_ipp.h"
45 #include "dce/dce_transform.h"
46 #include "dce80/dce80_opp.h"
47 #include "dce110/dce110_ipp.h"
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"
52
53 #include "reg_helper.h"
54
55 /* TODO remove this include */
56
57 #ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
58 #include "gmc/gmc_7_1_d.h"
59 #include "gmc/gmc_7_1_sh_mask.h"
60 #endif
61
62 #ifndef mmDP_DPHY_INTERNAL_CTRL
63 #define mmDP_DPHY_INTERNAL_CTRL 0x1CDE
64 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE
65 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE
66 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE
67 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE
68 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE
69 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE
70 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE
71 #endif
72
73
74 #ifndef mmBIOS_SCRATCH_2
75 #define mmBIOS_SCRATCH_2 0x05CB
76 #define mmBIOS_SCRATCH_6 0x05CF
77 #endif
78
79 #ifndef mmDP_DPHY_FAST_TRAINING
80 #define mmDP_DPHY_FAST_TRAINING 0x1CCE
81 #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE
82 #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE
83 #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE
84 #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE
85 #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE
86 #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE
87 #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE
88 #endif
89
90
91 #ifndef mmHPD_DC_HPD_CONTROL
92 #define mmHPD_DC_HPD_CONTROL 0x189A
93 #define mmHPD0_DC_HPD_CONTROL 0x189A
94 #define mmHPD1_DC_HPD_CONTROL 0x18A2
95 #define mmHPD2_DC_HPD_CONTROL 0x18AA
96 #define mmHPD3_DC_HPD_CONTROL 0x18B2
97 #define mmHPD4_DC_HPD_CONTROL 0x18BA
98 #define mmHPD5_DC_HPD_CONTROL 0x18C2
99 #endif
100
101 #define DCE11_DIG_FE_CNTL 0x4a00
102 #define DCE11_DIG_BE_CNTL 0x4a47
103 #define DCE11_DP_SEC 0x4ac3
104
105 static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = {
106 {
107 .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
108 .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL),
109 .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
110 - mmDPG_WATERMARK_MASK_CONTROL),
111 },
112 {
113 .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
114 .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
115 .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
116 - mmDPG_WATERMARK_MASK_CONTROL),
117 },
118 {
119 .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
120 .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
121 .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
122 - mmDPG_WATERMARK_MASK_CONTROL),
123 },
124 {
125 .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
126 .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
127 .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL
128 - mmDPG_WATERMARK_MASK_CONTROL),
129 },
130 {
131 .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
132 .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
133 .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL
134 - mmDPG_WATERMARK_MASK_CONTROL),
135 },
136 {
137 .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
138 .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
139 .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL
140 - mmDPG_WATERMARK_MASK_CONTROL),
141 }
142 };
143
144 static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = {
145 {
146 .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL),
147 .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
148 - mmDPG_WATERMARK_MASK_CONTROL),
149 .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL
150 - mmPIPE0_DMIF_BUFFER_CONTROL),
151 },
152 {
153 .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
154 .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
155 - mmDPG_WATERMARK_MASK_CONTROL),
156 .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL
157 - mmPIPE0_DMIF_BUFFER_CONTROL),
158 },
159 {
160 .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
161 .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
162 - mmDPG_WATERMARK_MASK_CONTROL),
163 .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL
164 - mmPIPE0_DMIF_BUFFER_CONTROL),
165 },
166 {
167 .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
168 .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL
169 - mmDPG_WATERMARK_MASK_CONTROL),
170 .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL
171 - mmPIPE0_DMIF_BUFFER_CONTROL),
172 },
173 {
174 .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
175 .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL
176 - mmDPG_WATERMARK_MASK_CONTROL),
177 .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL
178 - mmPIPE0_DMIF_BUFFER_CONTROL),
179 },
180 {
181 .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
182 .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL
183 - mmDPG_WATERMARK_MASK_CONTROL),
184 .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL
185 - mmPIPE0_DMIF_BUFFER_CONTROL),
186 }
187 };
188
189 static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = {
190 {
191 .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL),
192 },
193 {
194 .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL),
195 },
196 {
197 .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL),
198 },
199 {
200 .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL),
201 },
202 {
203 .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL),
204 },
205 {
206 .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL),
207 }
208 };
209
210 /* set register offset */
211 #define SR(reg_name)\
212 .reg_name = mm ## reg_name
213
214 /* set register offset with instance */
215 #define SRI(reg_name, block, id)\
216 .reg_name = mm ## block ## id ## _ ## reg_name
217
218 #define transform_regs(id)\
219 [id] = {\
220 XFM_COMMON_REG_LIST_DCE_BASE(id)\
221 }
222
223 static const struct dce_transform_registers xfm_regs[] = {
224 transform_regs(0),
225 transform_regs(1),
226 transform_regs(2),
227 transform_regs(3),
228 transform_regs(4),
229 transform_regs(5)
230 };
231
232 static const struct dce_transform_shift xfm_shift = {
233 XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
234 };
235
236 static const struct dce_transform_mask xfm_mask = {
237 XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
238 };
239
240 #define aux_regs(id)\
241 [id] = {\
242 AUX_REG_LIST(id)\
243 }
244
245 static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {
246 aux_regs(0),
247 aux_regs(1),
248 aux_regs(2),
249 aux_regs(3),
250 aux_regs(4),
251 aux_regs(5)
252 };
253
254 #define hpd_regs(id)\
255 [id] = {\
256 HPD_REG_LIST(id)\
257 }
258
259 static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {
260 hpd_regs(0),
261 hpd_regs(1),
262 hpd_regs(2),
263 hpd_regs(3),
264 hpd_regs(4),
265 hpd_regs(5)
266 };
267
268 #define link_regs(id)\
269 [id] = {\
270 LE_DCE80_REG_LIST(id)\
271 }
272
273 static const struct dce110_link_enc_registers link_enc_regs[] = {
274 link_regs(0),
275 link_regs(1),
276 link_regs(2),
277 link_regs(3),
278 link_regs(4),
279 link_regs(5),
280 link_regs(6),
281 };
282
283 #define stream_enc_regs(id)\
284 [id] = {\
285 SE_COMMON_REG_LIST_DCE_BASE(id),\
286 .AFMT_CNTL = 0,\
287 }
288
289 static const struct dce110_stream_enc_registers stream_enc_regs[] = {
290 stream_enc_regs(0),
291 stream_enc_regs(1),
292 stream_enc_regs(2),
293 stream_enc_regs(3),
294 stream_enc_regs(4),
295 stream_enc_regs(5)
296 };
297
298 static const struct dce_stream_encoder_shift se_shift = {
299 SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT)
300 };
301
302 static const struct dce_stream_encoder_mask se_mask = {
303 SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK)
304 };
305
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
325 static const struct dce_aduio_mask audio_mask = {
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 = {
350 .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
351 };
352
353 static const struct resource_caps res_cap = {
354 .num_timing_generator = 6,
355 .num_audio = 6,
356 .num_stream_encoder = 6,
357 .num_pll = 3,
358 };
359
360 #define CTX ctx
361 #define REG(reg) mm ## reg
362
363 #ifndef mmCC_DC_HDMI_STRAPS
364 #define mmCC_DC_HDMI_STRAPS 0x1918
365 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40
366 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6
367 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700
368 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8
369 #endif
370
371 static void read_dce_straps(
372 struct dc_context *ctx,
373 struct resource_straps *straps)
374 {
375 REG_GET_2(CC_DC_HDMI_STRAPS,
376 HDMI_DISABLE, &straps->hdmi_disable,
377 AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
378
379 REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);
380 }
381
382 static struct audio *create_audio(
383 struct dc_context *ctx, unsigned int inst)
384 {
385 return dce_audio_create(ctx, inst,
386 &audio_regs[inst], &audio_shift, &audio_mask);
387 }
388
389 static struct timing_generator *dce80_timing_generator_create(
390 struct dc_context *ctx,
391 uint32_t instance,
392 const struct dce110_timing_generator_offsets *offsets)
393 {
394 struct dce110_timing_generator *tg110 =
395 dm_alloc(sizeof(struct dce110_timing_generator));
396
397 if (!tg110)
398 return NULL;
399
400 if (dce80_timing_generator_construct(tg110, ctx, instance, offsets))
401 return &tg110->base;
402
403 BREAK_TO_DEBUGGER();
404 dm_free(tg110);
405 return NULL;
406 }
407
408 static struct stream_encoder *dce80_stream_encoder_create(
409 enum engine_id eng_id,
410 struct dc_context *ctx)
411 {
412 struct dce110_stream_encoder *enc110 =
413 dm_alloc(sizeof(struct dce110_stream_encoder));
414
415 if (!enc110)
416 return NULL;
417
418 if (dce110_stream_encoder_construct(
419 enc110, ctx, ctx->dc_bios, eng_id,
420 &stream_enc_regs[eng_id], &se_shift, &se_mask))
421 return &enc110->base;
422
423 BREAK_TO_DEBUGGER();
424 dm_free(enc110);
425 return NULL;
426 }
427
428 #define SRII(reg_name, block, id)\
429 .reg_name[id] = mm ## block ## id ## _ ## reg_name
430
431 static const struct dce_hwseq_registers hwseq_reg = {
432 HWSEQ_DCE8_REG_LIST()
433 };
434
435 static const struct dce_hwseq_shift hwseq_shift = {
436 HWSEQ_DCE8_MASK_SH_LIST(__SHIFT)
437 };
438
439 static const struct dce_hwseq_mask hwseq_mask = {
440 HWSEQ_DCE8_MASK_SH_LIST(_MASK)
441 };
442
443 static struct dce_hwseq *dce80_hwseq_create(
444 struct dc_context *ctx)
445 {
446 struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq));
447
448 if (hws) {
449 hws->ctx = ctx;
450 hws->regs = &hwseq_reg;
451 hws->shifts = &hwseq_shift;
452 hws->masks = &hwseq_mask;
453 }
454 return hws;
455 }
456
457 static const struct resource_create_funcs res_create_funcs = {
458 .read_dce_straps = read_dce_straps,
459 .create_audio = create_audio,
460 .create_stream_encoder = dce80_stream_encoder_create,
461 .create_hwseq = dce80_hwseq_create,
462 };
463
464 #define mi_inst_regs(id) { \
465 MI_DCE8_REG_LIST(id), \
466 .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \
467 }
468 static const struct dce_mem_input_registers mi_regs[] = {
469 mi_inst_regs(0),
470 mi_inst_regs(1),
471 mi_inst_regs(2),
472 mi_inst_regs(3),
473 mi_inst_regs(4),
474 mi_inst_regs(5),
475 };
476
477 static const struct dce_mem_input_shift mi_shifts = {
478 MI_DCE8_MASK_SH_LIST(__SHIFT),
479 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT
480 };
481
482 static const struct dce_mem_input_mask mi_masks = {
483 MI_DCE8_MASK_SH_LIST(_MASK),
484 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
485 };
486
487 static struct mem_input *dce80_mem_input_create(
488 struct dc_context *ctx,
489 uint32_t inst,
490 const struct dce110_mem_input_reg_offsets *offsets)
491 {
492 struct dce110_mem_input *mem_input80 =
493 dm_alloc(sizeof(struct dce110_mem_input));
494
495 if (!mem_input80)
496 return NULL;
497
498 if (dce80_mem_input_construct(mem_input80, ctx, inst, offsets)) {
499 struct mem_input *mi = &mem_input80->base;
500
501 mi->regs = &mi_regs[inst];
502 mi->shifts = &mi_shifts;
503 mi->masks = &mi_masks;
504 mi->wa.single_head_rdreq_dmif_limit = 2;
505 return mi;
506 }
507
508 BREAK_TO_DEBUGGER();
509 dm_free(mem_input80);
510 return NULL;
511 }
512
513 static void dce80_transform_destroy(struct transform **xfm)
514 {
515 dm_free(TO_DCE_TRANSFORM(*xfm));
516 *xfm = NULL;
517 }
518
519 static struct transform *dce80_transform_create(
520 struct dc_context *ctx,
521 uint32_t inst)
522 {
523 struct dce_transform *transform =
524 dm_alloc(sizeof(struct dce_transform));
525
526 if (!transform)
527 return NULL;
528
529 if (dce_transform_construct(transform, ctx, inst,
530 &xfm_regs[inst], &xfm_shift, &xfm_mask)) {
531 transform->prescaler_on = false;
532 return &transform->base;
533 }
534
535 BREAK_TO_DEBUGGER();
536 dm_free(transform);
537 return NULL;
538 }
539
540 static struct input_pixel_processor *dce80_ipp_create(
541 struct dc_context *ctx,
542 uint32_t inst,
543 const struct dce110_ipp_reg_offsets *offset)
544 {
545 struct dce110_ipp *ipp =
546 dm_alloc(sizeof(struct dce110_ipp));
547
548 if (!ipp)
549 return NULL;
550
551 if (dce80_ipp_construct(ipp, ctx, inst, offset))
552 return &ipp->base;
553
554 BREAK_TO_DEBUGGER();
555 dm_free(ipp);
556 return NULL;
557 }
558
559 struct link_encoder *dce80_link_encoder_create(
560 const struct encoder_init_data *enc_init_data)
561 {
562 struct dce110_link_encoder *enc110 =
563 dm_alloc(sizeof(struct dce110_link_encoder));
564
565 if (!enc110)
566 return NULL;
567
568 if (dce110_link_encoder_construct(
569 enc110,
570 enc_init_data,
571 &link_enc_regs[enc_init_data->transmitter],
572 &link_enc_aux_regs[enc_init_data->channel - 1],
573 &link_enc_hpd_regs[enc_init_data->hpd_source])) {
574
575 enc110->base.features.ycbcr420_supported = false;
576 enc110->base.features.max_hdmi_pixel_clock = 297000;
577 return &enc110->base;
578 }
579
580 BREAK_TO_DEBUGGER();
581 dm_free(enc110);
582 return NULL;
583 }
584
585 struct clock_source *dce80_clock_source_create(
586 struct dc_context *ctx,
587 struct dc_bios *bios,
588 enum clock_source_id id,
589 const struct dce110_clk_src_regs *regs,
590 bool dp_clk_src)
591 {
592 struct dce110_clk_src *clk_src =
593 dm_alloc(sizeof(struct dce110_clk_src));
594
595 if (!clk_src)
596 return NULL;
597
598 if (dce110_clk_src_construct(clk_src, ctx, bios, id,
599 regs, &cs_shift, &cs_mask)) {
600 clk_src->base.dp_clk_src = dp_clk_src;
601 return &clk_src->base;
602 }
603
604 BREAK_TO_DEBUGGER();
605 return NULL;
606 }
607
608 void dce80_clock_source_destroy(struct clock_source **clk_src)
609 {
610 dm_free(TO_DCE110_CLK_SRC(*clk_src));
611 *clk_src = NULL;
612 }
613
614 static void destruct(struct dce110_resource_pool *pool)
615 {
616 unsigned int i;
617
618 for (i = 0; i < pool->base.pipe_count; i++) {
619 if (pool->base.opps[i] != NULL)
620 dce80_opp_destroy(&pool->base.opps[i]);
621
622 if (pool->base.transforms[i] != NULL)
623 dce80_transform_destroy(&pool->base.transforms[i]);
624
625 if (pool->base.ipps[i] != NULL)
626 dce80_ipp_destroy(&pool->base.ipps[i]);
627
628 if (pool->base.mis[i] != NULL) {
629 dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i]));
630 pool->base.mis[i] = NULL;
631 }
632
633 if (pool->base.timing_generators[i] != NULL) {
634 dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
635 pool->base.timing_generators[i] = NULL;
636 }
637 }
638
639 for (i = 0; i < pool->base.stream_enc_count; i++) {
640 if (pool->base.stream_enc[i] != NULL)
641 dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));
642 }
643
644 for (i = 0; i < pool->base.clk_src_count; i++) {
645 if (pool->base.clock_sources[i] != NULL) {
646 dce80_clock_source_destroy(&pool->base.clock_sources[i]);
647 }
648 }
649
650 if (pool->base.dp_clock_source != NULL)
651 dce80_clock_source_destroy(&pool->base.dp_clock_source);
652
653 for (i = 0; i < pool->base.audio_count; i++) {
654 if (pool->base.audios[i] != NULL) {
655 dce_aud_destroy(&pool->base.audios[i]);
656 }
657 }
658
659 if (pool->base.display_clock != NULL) {
660 pool->base.display_clock->funcs->destroy(
661 &pool->base.display_clock);
662 pool->base.display_clock = NULL;
663 }
664
665 if (pool->base.irqs != NULL) {
666 dal_irq_service_destroy(&pool->base.irqs);
667 }
668 }
669
670 static enum dc_status validate_mapped_resource(
671 const struct core_dc *dc,
672 struct validate_context *context)
673 {
674 enum dc_status status = DC_OK;
675 uint8_t i, j, k;
676
677 for (i = 0; i < context->target_count; i++) {
678 struct core_target *target = context->targets[i];
679
680 for (j = 0; j < target->public.stream_count; j++) {
681 struct core_stream *stream =
682 DC_STREAM_TO_CORE(target->public.streams[j]);
683 struct core_link *link = stream->sink->link;
684
685 if (resource_is_stream_unchanged(dc->current_context, stream))
686 continue;
687
688 for (k = 0; k < MAX_PIPES; k++) {
689 struct pipe_ctx *pipe_ctx =
690 &context->res_ctx.pipe_ctx[k];
691
692 if (context->res_ctx.pipe_ctx[k].stream != stream)
693 continue;
694
695 if (!pipe_ctx->tg->funcs->validate_timing(
696 pipe_ctx->tg, &stream->public.timing))
697 return DC_FAIL_CONTROLLER_VALIDATE;
698
699 status = dce110_resource_build_pipe_hw_param(pipe_ctx);
700
701 if (status != DC_OK)
702 return status;
703
704 if (!link->link_enc->funcs->validate_output_with_stream(
705 link->link_enc,
706 pipe_ctx))
707 return DC_FAIL_ENC_VALIDATE;
708
709 /* TODO: validate audio ASIC caps, encoder */
710
711 status = dc_link_validate_mode_timing(stream,
712 link,
713 &stream->public.timing);
714
715 if (status != DC_OK)
716 return status;
717
718 resource_build_info_frame(pipe_ctx);
719
720 /* do not need to validate non root pipes */
721 break;
722 }
723 }
724 }
725
726 return DC_OK;
727 }
728
729 enum dc_status dce80_validate_bandwidth(
730 const struct core_dc *dc,
731 struct validate_context *context)
732 {
733 /* TODO implement when needed but for now hardcode max value*/
734 context->bw_results.dispclk_khz = 681000;
735 context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER;
736
737 return DC_OK;
738 }
739
740 static bool dce80_validate_surface_sets(
741 const struct dc_validation_set set[],
742 int set_count)
743 {
744 int i;
745
746 for (i = 0; i < set_count; i++) {
747 if (set[i].surface_count == 0)
748 continue;
749
750 if (set[i].surface_count > 1)
751 return false;
752
753 if (set[i].surfaces[0]->clip_rect.width
754 != set[i].target->streams[0]->src.width
755 || set[i].surfaces[0]->clip_rect.height
756 != set[i].target->streams[0]->src.height)
757 return false;
758 if (set[i].surfaces[0]->format
759 >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
760 return false;
761 }
762
763 return true;
764 }
765
766 enum dc_status dce80_validate_with_context(
767 const struct core_dc *dc,
768 const struct dc_validation_set set[],
769 int set_count,
770 struct validate_context *context)
771 {
772 struct dc_context *dc_ctx = dc->ctx;
773 enum dc_status result = DC_ERROR_UNEXPECTED;
774 int i;
775
776 if (!dce80_validate_surface_sets(set, set_count))
777 return DC_FAIL_SURFACE_VALIDATE;
778
779 context->res_ctx.pool = dc->res_pool;
780
781 for (i = 0; i < set_count; i++) {
782 context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
783 dc_target_retain(&context->targets[i]->public);
784 context->target_count++;
785 }
786
787 result = resource_map_pool_resources(dc, context);
788
789 if (result == DC_OK)
790 result = resource_map_clock_resources(dc, context);
791
792 if (!resource_validate_attach_surfaces(
793 set, set_count, dc->current_context, context)) {
794 DC_ERROR("Failed to attach surface to target!\n");
795 return DC_FAIL_ATTACH_SURFACES;
796 }
797
798 if (result == DC_OK)
799 result = validate_mapped_resource(dc, context);
800
801 if (result == DC_OK)
802 result = resource_build_scaling_params_for_context(dc, context);
803
804 if (result == DC_OK)
805 result = dce80_validate_bandwidth(dc, context);
806
807 return result;
808 }
809
810 enum dc_status dce80_validate_guaranteed(
811 const struct core_dc *dc,
812 const struct dc_target *dc_target,
813 struct validate_context *context)
814 {
815 enum dc_status result = DC_ERROR_UNEXPECTED;
816
817 context->res_ctx.pool = dc->res_pool;
818
819 context->targets[0] = DC_TARGET_TO_CORE(dc_target);
820 dc_target_retain(&context->targets[0]->public);
821 context->target_count++;
822
823 result = resource_map_pool_resources(dc, context);
824
825 if (result == DC_OK)
826 result = resource_map_clock_resources(dc, context);
827
828 if (result == DC_OK)
829 result = validate_mapped_resource(dc, context);
830
831 if (result == DC_OK) {
832 validate_guaranteed_copy_target(
833 context, dc->public.caps.max_targets);
834 result = resource_build_scaling_params_for_context(dc, context);
835 }
836
837 if (result == DC_OK)
838 result = dce80_validate_bandwidth(dc, context);
839
840 return result;
841 }
842
843 static void dce80_destroy_resource_pool(struct resource_pool **pool)
844 {
845 struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
846
847 destruct(dce110_pool);
848 dm_free(dce110_pool);
849 *pool = NULL;
850 }
851
852 static const struct resource_funcs dce80_res_pool_funcs = {
853 .destroy = dce80_destroy_resource_pool,
854 .link_enc_create = dce80_link_encoder_create,
855 .validate_with_context = dce80_validate_with_context,
856 .validate_guaranteed = dce80_validate_guaranteed,
857 .validate_bandwidth = dce80_validate_bandwidth
858 };
859
860 static enum clocks_state dce80_resource_convert_clock_state_pp_to_dc(
861 enum dm_pp_clocks_state pp_clock_state)
862 {
863 enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID;
864
865 switch (pp_clock_state) {
866 case DM_PP_CLOCKS_STATE_INVALID:
867 dc_clocks_state = CLOCKS_STATE_INVALID;
868 break;
869 case DM_PP_CLOCKS_STATE_ULTRA_LOW:
870 dc_clocks_state = CLOCKS_STATE_ULTRA_LOW;
871 break;
872 case DM_PP_CLOCKS_STATE_LOW:
873 dc_clocks_state = CLOCKS_STATE_LOW;
874 break;
875 case DM_PP_CLOCKS_STATE_NOMINAL:
876 dc_clocks_state = CLOCKS_STATE_NOMINAL;
877 break;
878 case DM_PP_CLOCKS_STATE_PERFORMANCE:
879 dc_clocks_state = CLOCKS_STATE_PERFORMANCE;
880 break;
881 case DM_PP_CLOCKS_DPM_STATE_LEVEL_4:
882 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4;
883 break;
884 case DM_PP_CLOCKS_DPM_STATE_LEVEL_5:
885 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5;
886 break;
887 case DM_PP_CLOCKS_DPM_STATE_LEVEL_6:
888 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6;
889 break;
890 case DM_PP_CLOCKS_DPM_STATE_LEVEL_7:
891 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7;
892 break;
893 default:
894 dc_clocks_state = CLOCKS_STATE_INVALID;
895 break;
896 }
897
898 return dc_clocks_state;
899 }
900
901 static bool construct(
902 uint8_t num_virtual_links,
903 struct core_dc *dc,
904 struct dce110_resource_pool *pool)
905 {
906 unsigned int i;
907 struct dc_context *ctx = dc->ctx;
908 struct firmware_info info;
909 struct dc_bios *bp;
910 struct dm_pp_static_clock_info static_clk_info = {0};
911
912 ctx->dc_bios->regs = &bios_regs;
913
914 pool->base.res_cap = &res_cap;
915 pool->base.funcs = &dce80_res_pool_funcs;
916
917
918 /*************************************************
919 * Resource + asic cap harcoding *
920 *************************************************/
921 pool->base.underlay_pipe_index = -1;
922 pool->base.pipe_count = res_cap.num_timing_generator;
923 dc->public.caps.max_downscale_ratio = 200;
924 dc->public.caps.i2c_speed_in_khz = 40;
925
926 /*************************************************
927 * Create resources *
928 *************************************************/
929
930 bp = ctx->dc_bios;
931
932 if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) &&
933 info.external_clock_source_frequency_for_dp != 0) {
934 pool->base.dp_clock_source =
935 dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
936
937 pool->base.clock_sources[0] =
938 dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false);
939 pool->base.clock_sources[1] =
940 dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
941 pool->base.clock_sources[2] =
942 dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
943 pool->base.clk_src_count = 3;
944
945 } else {
946 pool->base.dp_clock_source =
947 dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
948
949 pool->base.clock_sources[0] =
950 dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
951 pool->base.clock_sources[1] =
952 dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
953 pool->base.clk_src_count = 2;
954 }
955
956 if (pool->base.dp_clock_source == NULL) {
957 dm_error("DC: failed to create dp clock source!\n");
958 BREAK_TO_DEBUGGER();
959 goto res_create_fail;
960 }
961
962 for (i = 0; i < pool->base.clk_src_count; i++) {
963 if (pool->base.clock_sources[i] == NULL) {
964 dm_error("DC: failed to create clock sources!\n");
965 BREAK_TO_DEBUGGER();
966 goto res_create_fail;
967 }
968 }
969
970 pool->base.display_clock = dal_display_clock_dce80_create(ctx);
971 if (pool->base.display_clock == NULL) {
972 dm_error("DC: failed to create display clock!\n");
973 BREAK_TO_DEBUGGER();
974 goto res_create_fail;
975 }
976
977
978 if (dm_pp_get_static_clocks(ctx, &static_clk_info))
979 pool->base.display_clock->max_clks_state =
980 dce80_resource_convert_clock_state_pp_to_dc(
981 static_clk_info.max_clocks_state);
982
983 {
984 struct irq_service_init_data init_data;
985 init_data.ctx = dc->ctx;
986 pool->base.irqs = dal_irq_service_dce80_create(&init_data);
987 if (!pool->base.irqs)
988 goto res_create_fail;
989 }
990
991 for (i = 0; i < pool->base.pipe_count; i++) {
992 pool->base.timing_generators[i] = dce80_timing_generator_create(
993 ctx, i, &dce80_tg_offsets[i]);
994 if (pool->base.timing_generators[i] == NULL) {
995 BREAK_TO_DEBUGGER();
996 dm_error("DC: failed to create tg!\n");
997 goto res_create_fail;
998 }
999
1000 pool->base.mis[i] = dce80_mem_input_create(ctx, i,
1001 &dce80_mi_reg_offsets[i]);
1002 if (pool->base.mis[i] == NULL) {
1003 BREAK_TO_DEBUGGER();
1004 dm_error("DC: failed to create memory input!\n");
1005 goto res_create_fail;
1006 }
1007
1008 pool->base.ipps[i] = dce80_ipp_create(ctx, i, &ipp_reg_offsets[i]);
1009 if (pool->base.ipps[i] == NULL) {
1010 BREAK_TO_DEBUGGER();
1011 dm_error("DC: failed to create input pixel processor!\n");
1012 goto res_create_fail;
1013 }
1014
1015 pool->base.transforms[i] = dce80_transform_create(ctx, i);
1016 if (pool->base.transforms[i] == NULL) {
1017 BREAK_TO_DEBUGGER();
1018 dm_error("DC: failed to create transform!\n");
1019 goto res_create_fail;
1020 }
1021
1022 pool->base.opps[i] = dce80_opp_create(ctx, i);
1023 if (pool->base.opps[i] == NULL) {
1024 BREAK_TO_DEBUGGER();
1025 dm_error("DC: failed to create output pixel processor!\n");
1026 goto res_create_fail;
1027 }
1028 }
1029
1030 if (!resource_construct(num_virtual_links, dc, &pool->base,
1031 &res_create_funcs))
1032 goto res_create_fail;
1033
1034 /* Create hardware sequencer */
1035 if (!dce80_hw_sequencer_construct(dc))
1036 goto res_create_fail;
1037
1038 return true;
1039
1040 res_create_fail:
1041 destruct(pool);
1042 return false;
1043 }
1044
1045 struct resource_pool *dce80_create_resource_pool(
1046 uint8_t num_virtual_links,
1047 struct core_dc *dc)
1048 {
1049 struct dce110_resource_pool *pool =
1050 dm_alloc(sizeof(struct dce110_resource_pool));
1051
1052 if (!pool)
1053 return NULL;
1054
1055 if (construct(num_virtual_links, dc, pool))
1056 return &pool->base;
1057
1058 BREAK_TO_DEBUGGER();
1059 return NULL;
1060 }
1061