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