]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
drm/amd/display: remove get_min_clocks_state
[mirror_ubuntu-jammy-kernel.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_resource.c
CommitLineData
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
26#include "dm_services.h"
27
28#include "link_encoder.h"
29#include "stream_encoder.h"
30
31#include "resource.h"
32#include "dce110/dce110_resource.h"
33
34#include "include/irq_service_interface.h"
35#include "dce/dce_audio.h"
36#include "dce110/dce110_timing_generator.h"
37#include "irq/dce110/irq_service_dce110.h"
38#include "dce110/dce110_timing_generator_v.h"
39#include "dce/dce_link_encoder.h"
40#include "dce/dce_stream_encoder.h"
41#include "dce110/dce110_mem_input.h"
42#include "dce110/dce110_mem_input_v.h"
43#include "dce110/dce110_ipp.h"
44#include "dce/dce_transform.h"
45#include "dce110/dce110_transform_v.h"
46#include "dce110/dce110_opp.h"
47#include "dce110/dce110_opp_v.h"
48#include "dce/dce_clock_source.h"
49#include "dce/dce_hwseq.h"
50#include "dce110/dce110_hw_sequencer.h"
51
52#include "reg_helper.h"
53
54#include "dce/dce_11_0_d.h"
55#include "dce/dce_11_0_sh_mask.h"
56
57#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
58#include "gmc/gmc_8_2_d.h"
59#include "gmc/gmc_8_2_sh_mask.h"
60#endif
61
62#ifndef mmDP_DPHY_INTERNAL_CTRL
63 #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
64 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
65 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
66 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
67 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
68 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
69 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
70 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
71 #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
72 #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
73#endif
74
75#ifndef mmBIOS_SCRATCH_2
76 #define mmBIOS_SCRATCH_2 0x05CB
77 #define mmBIOS_SCRATCH_6 0x05CF
78#endif
79
80#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL
81 #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
82 #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
83 #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC
84 #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC
85 #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC
86 #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC
87 #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC
88 #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC
89#endif
90
91#ifndef mmDP_DPHY_FAST_TRAINING
92 #define mmDP_DPHY_FAST_TRAINING 0x4ABC
93 #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC
94 #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC
95 #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC
96 #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC
97 #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC
98 #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC
99 #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC
100#endif
101
102#ifndef DPHY_RX_FAST_TRAINING_CAPABLE
103 #define DPHY_RX_FAST_TRAINING_CAPABLE 0x1
104#endif
105
106static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = {
107 {
108 .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
109 .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
110 },
111 {
112 .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
113 .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
114 },
115 {
116 .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
117 .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
118 },
119 {
120 .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
121 .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
122 },
123 {
124 .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
125 .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
126 },
127 {
128 .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
129 .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
130 }
131};
132
133static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = {
134 {
135 .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
136 .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
137 - mmDPG_WATERMARK_MASK_CONTROL),
138 .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL
139 - mmPIPE0_DMIF_BUFFER_CONTROL),
140 },
141 {
142 .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
143 .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
144 - mmDPG_WATERMARK_MASK_CONTROL),
145 .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL
146 - mmPIPE0_DMIF_BUFFER_CONTROL),
147 },
148 {
149 .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
150 .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
151 - mmDPG_WATERMARK_MASK_CONTROL),
152 .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL
153 - mmPIPE0_DMIF_BUFFER_CONTROL),
154 }
155};
156
157
158static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = {
159{
160 .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL),
161},
162{
163 .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL),
164},
165{
166 .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL),
167},
168{
169 .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL),
170},
171{
172 .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL),
173},
174{
175 .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL),
176}
177};
178
179
180
181
182/* set register offset */
183#define SR(reg_name)\
184 .reg_name = mm ## reg_name
185
186/* set register offset with instance */
187#define SRI(reg_name, block, id)\
188 .reg_name = mm ## block ## id ## _ ## reg_name
189
190
191#define transform_regs(id)\
192[id] = {\
193 XFM_COMMON_REG_LIST_DCE110(id)\
194}
195
196static const struct dce_transform_registers xfm_regs[] = {
197 transform_regs(0),
198 transform_regs(1),
199 transform_regs(2)
200};
201
202static const struct dce_transform_shift xfm_shift = {
203 XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
204};
205
206static const struct dce_transform_mask xfm_mask = {
207 XFM_COMMON_MASK_SH_LIST_DCE110(_MASK)
208};
209
210#define aux_regs(id)\
211[id] = {\
212 AUX_REG_LIST(id)\
213}
214
215static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {
216 aux_regs(0),
217 aux_regs(1),
218 aux_regs(2),
219 aux_regs(3),
220 aux_regs(4),
221 aux_regs(5)
222};
223
224#define hpd_regs(id)\
225[id] = {\
226 HPD_REG_LIST(id)\
227}
228
229static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {
230 hpd_regs(0),
231 hpd_regs(1),
232 hpd_regs(2),
233 hpd_regs(3),
234 hpd_regs(4),
235 hpd_regs(5)
236};
237
238
239#define link_regs(id)\
240[id] = {\
241 LE_DCE110_REG_LIST(id)\
242}
243
244static const struct dce110_link_enc_registers link_enc_regs[] = {
245 link_regs(0),
246 link_regs(1),
247 link_regs(2),
248 link_regs(3),
249 link_regs(4),
250 link_regs(5),
251 link_regs(6),
252};
253
254#define stream_enc_regs(id)\
255[id] = {\
256 SE_COMMON_REG_LIST(id),\
257 .TMDS_CNTL = 0,\
258}
259
260static const struct dce110_stream_enc_registers stream_enc_regs[] = {
261 stream_enc_regs(0),
262 stream_enc_regs(1),
263 stream_enc_regs(2)
264};
265
266static const struct dce_stream_encoder_shift se_shift = {
267 SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
268};
269
270static const struct dce_stream_encoder_mask se_mask = {
271 SE_COMMON_MASK_SH_LIST_DCE110(_MASK)
272};
273
274#define audio_regs(id)\
275[id] = {\
276 AUD_COMMON_REG_LIST(id)\
277}
278
279static const struct dce_audio_registers audio_regs[] = {
280 audio_regs(0),
281 audio_regs(1),
282 audio_regs(2),
283 audio_regs(3),
284 audio_regs(4),
285 audio_regs(5),
286 audio_regs(6),
287};
288
289static const struct dce_audio_shift audio_shift = {
290 AUD_COMMON_MASK_SH_LIST(__SHIFT)
291};
292
293static const struct dce_aduio_mask audio_mask = {
294 AUD_COMMON_MASK_SH_LIST(_MASK)
295};
296
297/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */
298static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = {
299{
300 .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
301 .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
302 .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
303},
304{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
305 .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
306 .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
307},
308{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
309 .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
310 .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
311},
312{
313 .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
314 .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
315 .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
316},
317{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
318 .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
319 .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
320},
321{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
322 .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
323 .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
324}
325};
326
327#define clk_src_regs(id)\
328[id] = {\
329 CS_COMMON_REG_LIST_DCE_100_110(id),\
330}
331
332static const struct dce110_clk_src_regs clk_src_regs[] = {
333 clk_src_regs(0),
334 clk_src_regs(1),
335 clk_src_regs(2)
336};
337
338static const struct dce110_clk_src_shift cs_shift = {
339 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
340};
341
342static const struct dce110_clk_src_mask cs_mask = {
343 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
344};
345
346static const struct bios_registers bios_regs = {
347 .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
348};
349
350static const struct resource_caps carrizo_resource_cap = {
351 .num_timing_generator = 3,
352 .num_video_plane = 1,
353 .num_audio = 3,
354 .num_stream_encoder = 3,
355 .num_pll = 2,
356};
357
358static const struct resource_caps stoney_resource_cap = {
359 .num_timing_generator = 2,
360 .num_video_plane = 1,
361 .num_audio = 3,
362 .num_stream_encoder = 3,
363 .num_pll = 2,
364};
365
366#define CTX ctx
367#define REG(reg) mm ## reg
368
369#ifndef mmCC_DC_HDMI_STRAPS
370#define mmCC_DC_HDMI_STRAPS 0x4819
371#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40
372#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6
373#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700
374#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8
375#endif
376
377static void read_dce_straps(
378 struct dc_context *ctx,
379 struct resource_straps *straps)
380{
381 REG_GET_2(CC_DC_HDMI_STRAPS,
382 HDMI_DISABLE, &straps->hdmi_disable,
383 AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
384
385 REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);
386}
387
388static struct audio *create_audio(
389 struct dc_context *ctx, unsigned int inst)
390{
391 return dce_audio_create(ctx, inst,
392 &audio_regs[inst], &audio_shift, &audio_mask);
393}
394
395static struct timing_generator *dce110_timing_generator_create(
396 struct dc_context *ctx,
397 uint32_t instance,
398 const struct dce110_timing_generator_offsets *offsets)
399{
400 struct dce110_timing_generator *tg110 =
401 dm_alloc(sizeof(struct dce110_timing_generator));
402
403 if (!tg110)
404 return NULL;
405
406 if (dce110_timing_generator_construct(tg110, ctx, instance, offsets))
407 return &tg110->base;
408
409 BREAK_TO_DEBUGGER();
410 dm_free(tg110);
411 return NULL;
412}
413
414static struct stream_encoder *dce110_stream_encoder_create(
415 enum engine_id eng_id,
416 struct dc_context *ctx)
417{
418 struct dce110_stream_encoder *enc110 =
419 dm_alloc(sizeof(struct dce110_stream_encoder));
420
421 if (!enc110)
422 return NULL;
423
424 if (dce110_stream_encoder_construct(
425 enc110, ctx, ctx->dc_bios, eng_id,
426 &stream_enc_regs[eng_id], &se_shift, &se_mask))
427 return &enc110->base;
428
429 BREAK_TO_DEBUGGER();
430 dm_free(enc110);
431 return NULL;
432}
433
434#define SRII(reg_name, block, id)\
435 .reg_name[id] = mm ## block ## id ## _ ## reg_name
436
437static const struct dce_hwseq_registers hwseq_stoney_reg = {
438 HWSEQ_ST_REG_LIST()
439};
440
441static const struct dce_hwseq_registers hwseq_cz_reg = {
442 HWSEQ_CZ_REG_LIST()
443};
444
445static const struct dce_hwseq_shift hwseq_shift = {
446 HWSEQ_DCE11_MASK_SH_LIST(__SHIFT),
447};
448
449static const struct dce_hwseq_mask hwseq_mask = {
450 HWSEQ_DCE11_MASK_SH_LIST(_MASK),
451};
452
453static struct dce_hwseq *dce110_hwseq_create(
454 struct dc_context *ctx)
455{
456 struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq));
457
458 if (hws) {
459 hws->ctx = ctx;
460 hws->regs = ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev) ?
461 &hwseq_stoney_reg : &hwseq_cz_reg;
462 hws->shifts = &hwseq_shift;
463 hws->masks = &hwseq_mask;
464 hws->wa.blnd_crtc_trigger = true;
465 }
466 return hws;
467}
468
469static const struct resource_create_funcs res_create_funcs = {
470 .read_dce_straps = read_dce_straps,
471 .create_audio = create_audio,
472 .create_stream_encoder = dce110_stream_encoder_create,
473 .create_hwseq = dce110_hwseq_create,
474};
475
476#define mi_inst_regs(id) { \
197062bf 477 MI_DCE11_REG_LIST(id), \
4562236b
HW
478 .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \
479}
480static const struct dce_mem_input_registers mi_regs[] = {
481 mi_inst_regs(0),
482 mi_inst_regs(1),
483 mi_inst_regs(2),
484};
485
486static const struct dce_mem_input_shift mi_shifts = {
197062bf 487 MI_DCE11_MASK_SH_LIST(__SHIFT),
4562236b
HW
488 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT
489};
490
491static const struct dce_mem_input_mask mi_masks = {
197062bf 492 MI_DCE11_MASK_SH_LIST(_MASK),
4562236b
HW
493 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
494};
495
496static struct mem_input *dce110_mem_input_create(
497 struct dc_context *ctx,
498 uint32_t inst,
499 const struct dce110_mem_input_reg_offsets *offset)
500{
501 struct dce110_mem_input *mem_input110 =
502 dm_alloc(sizeof(struct dce110_mem_input));
503
504 if (!mem_input110)
505 return NULL;
506
507 if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) {
508 struct mem_input *mi = &mem_input110->base;
509
510 mi->regs = &mi_regs[inst];
511 mi->shifts = &mi_shifts;
512 mi->masks = &mi_masks;
513 mi->wa.single_head_rdreq_dmif_limit = 3;
514 return mi;
515 }
516
517 BREAK_TO_DEBUGGER();
518 dm_free(mem_input110);
519 return NULL;
520}
521
522static void dce110_transform_destroy(struct transform **xfm)
523{
524 dm_free(TO_DCE_TRANSFORM(*xfm));
525 *xfm = NULL;
526}
527
528static struct transform *dce110_transform_create(
529 struct dc_context *ctx,
530 uint32_t inst)
531{
532 struct dce_transform *transform =
533 dm_alloc(sizeof(struct dce_transform));
534
535 if (!transform)
536 return NULL;
537
538 if (dce_transform_construct(transform, ctx, inst,
539 &xfm_regs[inst], &xfm_shift, &xfm_mask))
540 return &transform->base;
541
542 BREAK_TO_DEBUGGER();
543 dm_free(transform);
544 return NULL;
545}
546
547static struct input_pixel_processor *dce110_ipp_create(
548 struct dc_context *ctx,
549 uint32_t inst,
550 const struct dce110_ipp_reg_offsets *offsets)
551{
552 struct dce110_ipp *ipp =
553 dm_alloc(sizeof(struct dce110_ipp));
554
555 if (!ipp)
556 return NULL;
557
558 if (dce110_ipp_construct(ipp, ctx, inst, offsets))
559 return &ipp->base;
560
561 BREAK_TO_DEBUGGER();
562 dm_free(ipp);
563 return NULL;
564}
565
566struct link_encoder *dce110_link_encoder_create(
567 const struct encoder_init_data *enc_init_data)
568{
569 struct dce110_link_encoder *enc110 =
570 dm_alloc(sizeof(struct dce110_link_encoder));
571
572 if (!enc110)
573 return NULL;
574
575 if (dce110_link_encoder_construct(
576 enc110,
577 enc_init_data,
578 &link_enc_regs[enc_init_data->transmitter],
579 &link_enc_aux_regs[enc_init_data->channel - 1],
580 &link_enc_hpd_regs[enc_init_data->hpd_source])) {
581
582 enc110->base.features.ycbcr420_supported = false;
583 enc110->base.features.max_hdmi_pixel_clock = 594000;
584 return &enc110->base;
585 }
586
587 BREAK_TO_DEBUGGER();
588 dm_free(enc110);
589 return NULL;
590}
591
592static struct output_pixel_processor *dce110_opp_create(
593 struct dc_context *ctx,
594 uint32_t inst,
595 const struct dce110_opp_reg_offsets *offsets)
596{
597 struct dce110_opp *opp =
598 dm_alloc(sizeof(struct dce110_opp));
599
600 if (!opp)
601 return NULL;
602
603 if (dce110_opp_construct(opp,
604 ctx, inst, offsets))
605 return &opp->base;
606
607 BREAK_TO_DEBUGGER();
608 dm_free(opp);
609 return NULL;
610}
611
612struct clock_source *dce110_clock_source_create(
613 struct dc_context *ctx,
614 struct dc_bios *bios,
615 enum clock_source_id id,
616 const struct dce110_clk_src_regs *regs,
617 bool dp_clk_src)
618{
619 struct dce110_clk_src *clk_src =
620 dm_alloc(sizeof(struct dce110_clk_src));
621
622 if (!clk_src)
623 return NULL;
624
625 if (dce110_clk_src_construct(clk_src, ctx, bios, id,
626 regs, &cs_shift, &cs_mask)) {
627 clk_src->base.dp_clk_src = dp_clk_src;
628 return &clk_src->base;
629 }
630
631 BREAK_TO_DEBUGGER();
632 return NULL;
633}
634
635void dce110_clock_source_destroy(struct clock_source **clk_src)
636{
637 struct dce110_clk_src *dce110_clk_src;
638
639 if (!clk_src)
640 return;
641
642 dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src);
643
644 if (dce110_clk_src->dp_ss_params)
645 dm_free(dce110_clk_src->dp_ss_params);
646
647 if (dce110_clk_src->hdmi_ss_params)
648 dm_free(dce110_clk_src->hdmi_ss_params);
649
650 if (dce110_clk_src->dvi_ss_params)
651 dm_free(dce110_clk_src->dvi_ss_params);
652
653 dm_free(dce110_clk_src);
654 *clk_src = NULL;
655}
656
657static void destruct(struct dce110_resource_pool *pool)
658{
659 unsigned int i;
660
661 for (i = 0; i < pool->base.pipe_count; i++) {
662 if (pool->base.opps[i] != NULL)
663 dce110_opp_destroy(&pool->base.opps[i]);
664
665 if (pool->base.transforms[i] != NULL)
666 dce110_transform_destroy(&pool->base.transforms[i]);
667
668 if (pool->base.ipps[i] != NULL)
669 dce110_ipp_destroy(&pool->base.ipps[i]);
670
671 if (pool->base.mis[i] != NULL) {
672 dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i]));
673 pool->base.mis[i] = NULL;
674 }
675
676 if (pool->base.timing_generators[i] != NULL) {
677 dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
678 pool->base.timing_generators[i] = NULL;
679 }
680 }
681
682 for (i = 0; i < pool->base.stream_enc_count; i++) {
683 if (pool->base.stream_enc[i] != NULL)
684 dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));
685 }
686
687 for (i = 0; i < pool->base.clk_src_count; i++) {
688 if (pool->base.clock_sources[i] != NULL) {
689 dce110_clock_source_destroy(&pool->base.clock_sources[i]);
690 }
691 }
692
693 if (pool->base.dp_clock_source != NULL)
694 dce110_clock_source_destroy(&pool->base.dp_clock_source);
695
696 for (i = 0; i < pool->base.audio_count; i++) {
697 if (pool->base.audios[i] != NULL) {
698 dce_aud_destroy(&pool->base.audios[i]);
699 }
700 }
701
702 if (pool->base.display_clock != NULL) {
5d6d185f
DL
703 pool->base.display_clock->funcs->destroy(
704 &pool->base.display_clock);
705 pool->base.display_clock = NULL;
4562236b
HW
706 }
707
708 if (pool->base.irqs != NULL) {
709 dal_irq_service_destroy(&pool->base.irqs);
710 }
711}
712
713
714static void get_pixel_clock_parameters(
715 const struct pipe_ctx *pipe_ctx,
716 struct pixel_clk_params *pixel_clk_params)
717{
718 const struct core_stream *stream = pipe_ctx->stream;
719
720 /*TODO: is this halved for YCbCr 420? in that case we might want to move
721 * the pixel clock normalization for hdmi up to here instead of doing it
722 * in pll_adjust_pix_clk
723 */
724 pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
725 pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
726 pixel_clk_params->signal_type = pipe_ctx->stream->signal;
727 pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1;
728 /* TODO: un-hardcode*/
729 pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
730 LINK_RATE_REF_FREQ_IN_KHZ;
731 pixel_clk_params->flags.ENABLE_SS = 0;
732 pixel_clk_params->color_depth =
733 stream->public.timing.display_color_depth;
734 pixel_clk_params->flags.DISPLAY_BLANKED = 1;
735 pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding ==
736 PIXEL_ENCODING_YCBCR420);
737}
738
739void dce110_resource_build_bit_depth_reduction_params(
740 const struct core_stream *stream,
741 struct bit_depth_reduction_params *fmt_bit_depth)
742{
743 memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
744
745 /*TODO: Need to un-hardcode, refer to function with same name
746 * in dal2 hw_sequencer*/
747
748 fmt_bit_depth->flags.TRUNCATE_ENABLED = 0;
749 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0;
750 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0;
751
752 /* Diagnostics need consistent CRC of the image, that means
753 * dithering should not be enabled for Diagnostics. */
754 if (IS_DIAG_DC(stream->ctx->dce_environment) == false) {
755 switch (stream->public.timing.display_color_depth) {
756 case COLOR_DEPTH_666:
757 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
758 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
759 break;
760 case COLOR_DEPTH_888:
761 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
762 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
763 break;
764 case COLOR_DEPTH_101010:
765 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
766 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
767 break;
768 default:
769 break;
770 }
771 fmt_bit_depth->flags.RGB_RANDOM = 1;
772 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
773 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
774 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
775 }
776
777 return;
778}
779
780enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
781{
782 get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params);
783 pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
784 pipe_ctx->clock_source,
785 &pipe_ctx->pix_clk_params,
786 &pipe_ctx->pll_settings);
787 dce110_resource_build_bit_depth_reduction_params(pipe_ctx->stream,
788 &pipe_ctx->stream->bit_depth_params);
789 pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding;
790
791 return DC_OK;
792}
793
794static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx)
795{
796 if (pipe_ctx->pipe_idx != underlay_idx)
797 return true;
798 if (!pipe_ctx->surface)
799 return false;
800 if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
801 return false;
802 return true;
803}
804
805static enum dc_status validate_mapped_resource(
806 const struct core_dc *dc,
807 struct validate_context *context)
808{
809 enum dc_status status = DC_OK;
810 uint8_t i, j, k;
811
812 for (i = 0; i < context->target_count; i++) {
813 struct core_target *target = context->targets[i];
814
815 for (j = 0; j < target->public.stream_count; j++) {
816 struct core_stream *stream =
817 DC_STREAM_TO_CORE(target->public.streams[j]);
818 struct core_link *link = stream->sink->link;
819
820 if (resource_is_stream_unchanged(dc->current_context, stream))
821 continue;
822
823 for (k = 0; k < MAX_PIPES; k++) {
824 struct pipe_ctx *pipe_ctx =
825 &context->res_ctx.pipe_ctx[k];
826
827 if (context->res_ctx.pipe_ctx[k].stream != stream)
828 continue;
829
830 if (!is_surface_pixel_format_supported(pipe_ctx,
831 context->res_ctx.pool->underlay_pipe_index))
832 return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED;
833
834 if (!pipe_ctx->tg->funcs->validate_timing(
835 pipe_ctx->tg, &stream->public.timing))
836 return DC_FAIL_CONTROLLER_VALIDATE;
837
838 status = dce110_resource_build_pipe_hw_param(pipe_ctx);
839
840 if (status != DC_OK)
841 return status;
842
843 if (!link->link_enc->funcs->validate_output_with_stream(
844 link->link_enc,
845 pipe_ctx))
846 return DC_FAIL_ENC_VALIDATE;
847
848 /* TODO: validate audio ASIC caps, encoder */
849
850 status = dc_link_validate_mode_timing(stream,
851 link,
852 &stream->public.timing);
853
854 if (status != DC_OK)
855 return status;
856
857 resource_build_info_frame(pipe_ctx);
858
859 /* do not need to validate non root pipes */
860 break;
861 }
862 }
863 }
864
865 return DC_OK;
866}
867
868enum dc_status dce110_validate_bandwidth(
869 const struct core_dc *dc,
870 struct validate_context *context)
871{
872 enum dc_status result = DC_ERROR_UNEXPECTED;
873
874 dm_logger_write(
875 dc->ctx->logger, LOG_BANDWIDTH_CALCS,
876 "%s: start",
877 __func__);
878
879 if (!bw_calcs(
880 dc->ctx,
881 &dc->bw_dceip,
882 &dc->bw_vbios,
883 context->res_ctx.pipe_ctx,
884 context->res_ctx.pool->pipe_count,
885 &context->bw_results))
886 result = DC_FAIL_BANDWIDTH_VALIDATE;
887 else
888 result = DC_OK;
889
890 if (result == DC_FAIL_BANDWIDTH_VALIDATE)
891 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION,
892 "%s: %dx%d@%d Bandwidth validation failed!\n",
893 __func__,
894 context->targets[0]->public.streams[0]->timing.h_addressable,
895 context->targets[0]->public.streams[0]->timing.v_addressable,
896 context->targets[0]->public.streams[0]->timing.pix_clk_khz);
897
898 if (memcmp(&dc->current_context->bw_results,
899 &context->bw_results, sizeof(context->bw_results))) {
900 struct log_entry log_entry;
901 dm_logger_open(
902 dc->ctx->logger,
903 &log_entry,
904 LOG_BANDWIDTH_CALCS);
905 dm_logger_append(&log_entry, "%s: finish,\n"
906 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
907 "stutMark_b: %d stutMark_a: %d\n",
908 __func__,
909 context->bw_results.nbp_state_change_wm_ns[0].b_mark,
910 context->bw_results.nbp_state_change_wm_ns[0].a_mark,
911 context->bw_results.urgent_wm_ns[0].b_mark,
912 context->bw_results.urgent_wm_ns[0].a_mark,
913 context->bw_results.stutter_exit_wm_ns[0].b_mark,
914 context->bw_results.stutter_exit_wm_ns[0].a_mark);
915 dm_logger_append(&log_entry,
916 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
917 "stutMark_b: %d stutMark_a: %d\n",
918 context->bw_results.nbp_state_change_wm_ns[1].b_mark,
919 context->bw_results.nbp_state_change_wm_ns[1].a_mark,
920 context->bw_results.urgent_wm_ns[1].b_mark,
921 context->bw_results.urgent_wm_ns[1].a_mark,
922 context->bw_results.stutter_exit_wm_ns[1].b_mark,
923 context->bw_results.stutter_exit_wm_ns[1].a_mark);
924 dm_logger_append(&log_entry,
925 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
926 "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n",
927 context->bw_results.nbp_state_change_wm_ns[2].b_mark,
928 context->bw_results.nbp_state_change_wm_ns[2].a_mark,
929 context->bw_results.urgent_wm_ns[2].b_mark,
930 context->bw_results.urgent_wm_ns[2].a_mark,
931 context->bw_results.stutter_exit_wm_ns[2].b_mark,
932 context->bw_results.stutter_exit_wm_ns[2].a_mark,
933 context->bw_results.stutter_mode_enable);
934 dm_logger_append(&log_entry,
935 "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n"
936 "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n",
937 context->bw_results.cpuc_state_change_enable,
938 context->bw_results.cpup_state_change_enable,
939 context->bw_results.nbp_state_change_enable,
940 context->bw_results.all_displays_in_sync,
941 context->bw_results.dispclk_khz,
942 context->bw_results.required_sclk,
943 context->bw_results.required_sclk_deep_sleep,
944 context->bw_results.required_yclk,
945 context->bw_results.blackout_recovery_time_us);
946 dm_logger_close(&log_entry);
947 }
948 return result;
949}
950
951static bool dce110_validate_surface_sets(
952 const struct dc_validation_set set[],
953 int set_count)
954{
955 int i;
956
957 for (i = 0; i < set_count; i++) {
958 if (set[i].surface_count == 0)
959 continue;
960
961 if (set[i].surface_count > 2)
962 return false;
963
964 if (set[i].surfaces[0]->src_rect.width
965 != set[i].target->streams[0]->src.width
966 || set[i].surfaces[0]->src_rect.height
967 != set[i].target->streams[0]->src.height)
968 return false;
969 if (set[i].surfaces[0]->format
970 >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
971 return false;
972
973 if (set[i].surface_count == 2) {
974 if (set[i].surfaces[1]->format
975 < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
976 return false;
977 if (set[i].surfaces[1]->src_rect.width > 1920
978 || set[i].surfaces[1]->src_rect.height > 1080)
979 return false;
980
981 if (set[i].target->streams[0]->timing.pixel_encoding != PIXEL_ENCODING_RGB)
982 return false;
983 }
984 }
985
986 return true;
987}
988
989enum dc_status dce110_validate_with_context(
990 const struct core_dc *dc,
991 const struct dc_validation_set set[],
992 int set_count,
993 struct validate_context *context)
994{
995 struct dc_context *dc_ctx = dc->ctx;
996 enum dc_status result = DC_ERROR_UNEXPECTED;
997 int i;
998
999 if (!dce110_validate_surface_sets(set, set_count))
1000 return DC_FAIL_SURFACE_VALIDATE;
1001
1002 context->res_ctx.pool = dc->res_pool;
1003
1004 for (i = 0; i < set_count; i++) {
1005 context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
1006 dc_target_retain(&context->targets[i]->public);
1007 context->target_count++;
1008 }
1009
1010 result = resource_map_pool_resources(dc, context);
1011
1012 if (result == DC_OK)
1013 result = resource_map_clock_resources(dc, context);
1014
1015 if (!resource_validate_attach_surfaces(
1016 set, set_count, dc->current_context, context)) {
1017 DC_ERROR("Failed to attach surface to target!\n");
1018 return DC_FAIL_ATTACH_SURFACES;
1019 }
1020
1021 if (result == DC_OK)
1022 result = validate_mapped_resource(dc, context);
1023
1024 if (result == DC_OK)
1025 result = resource_build_scaling_params_for_context(dc, context);
1026
1027 if (result == DC_OK)
1028 result = dce110_validate_bandwidth(dc, context);
1029
1030 return result;
1031}
1032
1033enum dc_status dce110_validate_guaranteed(
1034 const struct core_dc *dc,
1035 const struct dc_target *dc_target,
1036 struct validate_context *context)
1037{
1038 enum dc_status result = DC_ERROR_UNEXPECTED;
1039
1040 context->res_ctx.pool = dc->res_pool;
1041
1042 context->targets[0] = DC_TARGET_TO_CORE(dc_target);
1043 dc_target_retain(&context->targets[0]->public);
1044 context->target_count++;
1045
1046 result = resource_map_pool_resources(dc, context);
1047
1048 if (result == DC_OK)
1049 result = resource_map_clock_resources(dc, context);
1050
1051 if (result == DC_OK)
1052 result = validate_mapped_resource(dc, context);
1053
1054 if (result == DC_OK) {
1055 validate_guaranteed_copy_target(
1056 context, dc->public.caps.max_targets);
1057 result = resource_build_scaling_params_for_context(dc, context);
1058 }
1059
1060 if (result == DC_OK)
1061 result = dce110_validate_bandwidth(dc, context);
1062
1063 return result;
1064}
1065
1066static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer(
1067 struct resource_context *res_ctx,
1068 struct core_stream *stream)
1069{
1070 unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index;
1071 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx];
1072
1073 if (res_ctx->pipe_ctx[underlay_idx].stream) {
1074 return NULL;
1075 }
1076
1077 pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx];
1078 pipe_ctx->mi = res_ctx->pool->mis[underlay_idx];
1079 /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/
1080 pipe_ctx->xfm = res_ctx->pool->transforms[underlay_idx];
1081 pipe_ctx->opp = res_ctx->pool->opps[underlay_idx];
1082 pipe_ctx->dis_clk = res_ctx->pool->display_clock;
1083 pipe_ctx->pipe_idx = underlay_idx;
1084
1085 pipe_ctx->stream = stream;
1086
1087 return pipe_ctx;
1088
1089}
1090
1091static void dce110_destroy_resource_pool(struct resource_pool **pool)
1092{
1093 struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
1094
1095 destruct(dce110_pool);
1096 dm_free(dce110_pool);
1097 *pool = NULL;
1098}
1099
1100
1101static const struct resource_funcs dce110_res_pool_funcs = {
1102 .destroy = dce110_destroy_resource_pool,
1103 .link_enc_create = dce110_link_encoder_create,
1104 .validate_with_context = dce110_validate_with_context,
1105 .validate_guaranteed = dce110_validate_guaranteed,
1106 .validate_bandwidth = dce110_validate_bandwidth,
1107 .acquire_idle_pipe_for_layer = dce110_acquire_idle_pipe_for_layer,
1108 .build_bit_depth_reduction_params =
1109 dce110_resource_build_bit_depth_reduction_params
1110};
1111
1112static void underlay_create(struct dc_context *ctx, struct resource_pool *pool)
1113{
1114 struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv));
1115 struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv));
1116 struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv));
1117 struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv));
1118
1119 dce110_opp_v_construct(dce110_oppv, ctx);
1120 dce110_timing_generator_v_construct(dce110_tgv, ctx);
1121 dce110_mem_input_v_construct(dce110_miv, ctx);
1122 dce110_transform_v_construct(dce110_xfmv, ctx);
1123
1124 pool->opps[pool->pipe_count] = &dce110_oppv->base;
1125 pool->timing_generators[pool->pipe_count] = &dce110_tgv->base;
1126 pool->mis[pool->pipe_count] = &dce110_miv->base;
1127 pool->transforms[pool->pipe_count] = &dce110_xfmv->base;
1128 pool->pipe_count++;
1129
1130 /* update the public caps to indicate an underlay is available */
1131 ctx->dc->caps.max_slave_planes = 1;
1132 ctx->dc->caps.max_slave_planes = 1;
1133}
1134
1135static void bw_calcs_data_update_from_pplib(struct core_dc *dc)
1136{
1137 struct dm_pp_clock_levels clks = {0};
1138
1139 /*do system clock*/
1140 dm_pp_get_clock_levels_by_type(
1141 dc->ctx,
1142 DM_PP_CLOCK_TYPE_ENGINE_CLK,
1143 &clks);
1144 /* convert all the clock fro kHz to fix point mHz */
1145 dc->bw_vbios.high_sclk = bw_frc_to_fixed(
1146 clks.clocks_in_khz[clks.num_levels-1], 1000);
1147 dc->bw_vbios.mid1_sclk = bw_frc_to_fixed(
1148 clks.clocks_in_khz[clks.num_levels/8], 1000);
1149 dc->bw_vbios.mid2_sclk = bw_frc_to_fixed(
1150 clks.clocks_in_khz[clks.num_levels*2/8], 1000);
1151 dc->bw_vbios.mid3_sclk = bw_frc_to_fixed(
1152 clks.clocks_in_khz[clks.num_levels*3/8], 1000);
1153 dc->bw_vbios.mid4_sclk = bw_frc_to_fixed(
1154 clks.clocks_in_khz[clks.num_levels*4/8], 1000);
1155 dc->bw_vbios.mid5_sclk = bw_frc_to_fixed(
1156 clks.clocks_in_khz[clks.num_levels*5/8], 1000);
1157 dc->bw_vbios.mid6_sclk = bw_frc_to_fixed(
1158 clks.clocks_in_khz[clks.num_levels*6/8], 1000);
1159 dc->bw_vbios.low_sclk = bw_frc_to_fixed(
1160 clks.clocks_in_khz[0], 1000);
1161 dc->sclk_lvls = clks;
1162
1163 /*do display clock*/
1164 dm_pp_get_clock_levels_by_type(
1165 dc->ctx,
1166 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
1167 &clks);
1168 dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed(
1169 clks.clocks_in_khz[clks.num_levels-1], 1000);
1170 dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed(
1171 clks.clocks_in_khz[clks.num_levels>>1], 1000);
1172 dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed(
1173 clks.clocks_in_khz[0], 1000);
1174
1175 /*do memory clock*/
1176 dm_pp_get_clock_levels_by_type(
1177 dc->ctx,
1178 DM_PP_CLOCK_TYPE_MEMORY_CLK,
1179 &clks);
1180
1181 dc->bw_vbios.low_yclk = bw_frc_to_fixed(
1182 clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000);
1183 dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
1184 clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER,
1185 1000);
1186 dc->bw_vbios.high_yclk = bw_frc_to_fixed(
1187 clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER,
1188 1000);
1189}
1190
1191enum clocks_state dce110_resource_convert_clock_state_pp_to_dc(
1192 enum dm_pp_clocks_state pp_clock_state)
1193{
1194 enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID;
1195
1196 switch (pp_clock_state) {
1197 case DM_PP_CLOCKS_STATE_INVALID:
1198 dc_clocks_state = CLOCKS_STATE_INVALID;
1199 break;
1200 case DM_PP_CLOCKS_STATE_ULTRA_LOW:
1201 dc_clocks_state = CLOCKS_STATE_ULTRA_LOW;
1202 break;
1203 case DM_PP_CLOCKS_STATE_LOW:
1204 dc_clocks_state = CLOCKS_STATE_LOW;
1205 break;
1206 case DM_PP_CLOCKS_STATE_NOMINAL:
1207 dc_clocks_state = CLOCKS_STATE_NOMINAL;
1208 break;
1209 case DM_PP_CLOCKS_STATE_PERFORMANCE:
1210 dc_clocks_state = CLOCKS_STATE_PERFORMANCE;
1211 break;
1212 case DM_PP_CLOCKS_DPM_STATE_LEVEL_4:
1213 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4;
1214 break;
1215 case DM_PP_CLOCKS_DPM_STATE_LEVEL_5:
1216 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5;
1217 break;
1218 case DM_PP_CLOCKS_DPM_STATE_LEVEL_6:
1219 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6;
1220 break;
1221 case DM_PP_CLOCKS_DPM_STATE_LEVEL_7:
1222 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7;
1223 break;
1224 default:
1225 dc_clocks_state = CLOCKS_STATE_INVALID;
1226 break;
1227 }
1228
1229 return dc_clocks_state;
1230}
1231
1232const struct resource_caps *dce110_resource_cap(
1233 struct hw_asic_id *asic_id)
1234{
1235 if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev))
1236 return &stoney_resource_cap;
1237 else
1238 return &carrizo_resource_cap;
1239}
1240
1241static bool construct(
1242 uint8_t num_virtual_links,
1243 struct core_dc *dc,
1244 struct dce110_resource_pool *pool,
1245 struct hw_asic_id asic_id)
1246{
1247 unsigned int i;
1248 struct dc_context *ctx = dc->ctx;
1249 struct firmware_info info;
1250 struct dc_bios *bp;
1251 struct dm_pp_static_clock_info static_clk_info = {0};
1252
1253 ctx->dc_bios->regs = &bios_regs;
1254
1255 pool->base.res_cap = dce110_resource_cap(&ctx->asic_id);
1256 pool->base.funcs = &dce110_res_pool_funcs;
1257
1258 /*************************************************
1259 * Resource + asic cap harcoding *
1260 *************************************************/
1261
1262 pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
1263 pool->base.underlay_pipe_index = pool->base.pipe_count;
1264
1265 dc->public.caps.max_downscale_ratio = 150;
1266 dc->public.caps.i2c_speed_in_khz = 100;
1267
1268 /*************************************************
1269 * Create resources *
1270 *************************************************/
1271
1272 bp = ctx->dc_bios;
1273
1274 if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) &&
1275 info.external_clock_source_frequency_for_dp != 0) {
1276 pool->base.dp_clock_source =
1277 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
1278
1279 pool->base.clock_sources[0] =
1280 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0,
1281 &clk_src_regs[0], false);
1282 pool->base.clock_sources[1] =
1283 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1,
1284 &clk_src_regs[1], false);
1285
1286 pool->base.clk_src_count = 2;
1287
1288 /* TODO: find out if CZ support 3 PLLs */
1289 }
1290
1291 if (pool->base.dp_clock_source == NULL) {
1292 dm_error("DC: failed to create dp clock source!\n");
1293 BREAK_TO_DEBUGGER();
1294 goto res_create_fail;
1295 }
1296
1297 for (i = 0; i < pool->base.clk_src_count; i++) {
1298 if (pool->base.clock_sources[i] == NULL) {
1299 dm_error("DC: failed to create clock sources!\n");
1300 BREAK_TO_DEBUGGER();
1301 goto res_create_fail;
1302 }
1303 }
1304
1305 pool->base.display_clock = dal_display_clock_dce110_create(ctx);
1306 if (pool->base.display_clock == NULL) {
1307 dm_error("DC: failed to create display clock!\n");
1308 BREAK_TO_DEBUGGER();
1309 goto res_create_fail;
1310 }
1311
1312 /* get static clock information for PPLIB or firmware, save
1313 * max_clock_state
1314 */
3bad7c5c
DL
1315 if (dm_pp_get_static_clocks(ctx, &static_clk_info))
1316 pool->base.display_clock->max_clks_state =
4562236b
HW
1317 dce110_resource_convert_clock_state_pp_to_dc(
1318 static_clk_info.max_clocks_state);
1319
4562236b
HW
1320 {
1321 struct irq_service_init_data init_data;
1322 init_data.ctx = dc->ctx;
1323 pool->base.irqs = dal_irq_service_dce110_create(&init_data);
1324 if (!pool->base.irqs)
1325 goto res_create_fail;
1326 }
1327
1328 for (i = 0; i < pool->base.pipe_count; i++) {
1329 pool->base.timing_generators[i] = dce110_timing_generator_create(
1330 ctx, i, &dce110_tg_offsets[i]);
1331 if (pool->base.timing_generators[i] == NULL) {
1332 BREAK_TO_DEBUGGER();
1333 dm_error("DC: failed to create tg!\n");
1334 goto res_create_fail;
1335 }
1336
1337 pool->base.mis[i] = dce110_mem_input_create(ctx, i,
1338 &dce110_mi_reg_offsets[i]);
1339 if (pool->base.mis[i] == NULL) {
1340 BREAK_TO_DEBUGGER();
1341 dm_error(
1342 "DC: failed to create memory input!\n");
1343 goto res_create_fail;
1344 }
1345
1346 pool->base.ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]);
1347 if (pool->base.ipps[i] == NULL) {
1348 BREAK_TO_DEBUGGER();
1349 dm_error(
1350 "DC: failed to create input pixel processor!\n");
1351 goto res_create_fail;
1352 }
1353
1354 pool->base.transforms[i] = dce110_transform_create(ctx, i);
1355 if (pool->base.transforms[i] == NULL) {
1356 BREAK_TO_DEBUGGER();
1357 dm_error(
1358 "DC: failed to create transform!\n");
1359 goto res_create_fail;
1360 }
1361
1362 pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]);
1363 if (pool->base.opps[i] == NULL) {
1364 BREAK_TO_DEBUGGER();
1365 dm_error(
1366 "DC: failed to create output pixel processor!\n");
1367 goto res_create_fail;
1368 }
1369 }
1370
1371 underlay_create(ctx, &pool->base);
1372
1373 if (!resource_construct(num_virtual_links, dc, &pool->base,
1374 &res_create_funcs))
1375 goto res_create_fail;
1376
1377 /* Create hardware sequencer */
1378 if (!dce110_hw_sequencer_construct(dc))
1379 goto res_create_fail;
1380
1381 if (ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev))
1382 bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_STONEY);
1383 else
1384 bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_CARRIZO);
1385
1386 bw_calcs_data_update_from_pplib(dc);
1387
1388 return true;
1389
1390res_create_fail:
1391 destruct(pool);
1392 return false;
1393}
1394
1395struct resource_pool *dce110_create_resource_pool(
1396 uint8_t num_virtual_links,
1397 struct core_dc *dc,
1398 struct hw_asic_id asic_id)
1399{
1400 struct dce110_resource_pool *pool =
1401 dm_alloc(sizeof(struct dce110_resource_pool));
1402
1403 if (!pool)
1404 return NULL;
1405
1406 if (construct(num_virtual_links, dc, pool, asic_id))
1407 return &pool->base;
1408
1409 BREAK_TO_DEBUGGER();
1410 return NULL;
1411}