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