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