]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
drm/amd/display: restyle display clock calls part 1
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_resource.c
1 /*
2 * Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include "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
106 static 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
133 static 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
158 static 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
196 static const struct dce_transform_registers xfm_regs[] = {
197 transform_regs(0),
198 transform_regs(1),
199 transform_regs(2)
200 };
201
202 static const struct dce_transform_shift xfm_shift = {
203 XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
204 };
205
206 static 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
215 static 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
229 static 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
244 static 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
260 static 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
266 static const struct dce_stream_encoder_shift se_shift = {
267 SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
268 };
269
270 static 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
279 static 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
289 static const struct dce_audio_shift audio_shift = {
290 AUD_COMMON_MASK_SH_LIST(__SHIFT)
291 };
292
293 static 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. */
298 static 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
332 static 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
338 static const struct dce110_clk_src_shift cs_shift = {
339 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
340 };
341
342 static const struct dce110_clk_src_mask cs_mask = {
343 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
344 };
345
346 static const struct bios_registers bios_regs = {
347 .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
348 };
349
350 static 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
358 static 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
377 static 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
388 static 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
395 static 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
414 static 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
437 static const struct dce_hwseq_registers hwseq_stoney_reg = {
438 HWSEQ_ST_REG_LIST()
439 };
440
441 static const struct dce_hwseq_registers hwseq_cz_reg = {
442 HWSEQ_CZ_REG_LIST()
443 };
444
445 static const struct dce_hwseq_shift hwseq_shift = {
446 HWSEQ_DCE11_MASK_SH_LIST(__SHIFT),
447 };
448
449 static const struct dce_hwseq_mask hwseq_mask = {
450 HWSEQ_DCE11_MASK_SH_LIST(_MASK),
451 };
452
453 static 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
469 static 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) { \
477 MI_DCE11_REG_LIST(id), \
478 .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \
479 }
480 static 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
486 static const struct dce_mem_input_shift mi_shifts = {
487 MI_DCE11_MASK_SH_LIST(__SHIFT),
488 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT
489 };
490
491 static const struct dce_mem_input_mask mi_masks = {
492 MI_DCE11_MASK_SH_LIST(_MASK),
493 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
494 };
495
496 static 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
522 static void dce110_transform_destroy(struct transform **xfm)
523 {
524 dm_free(TO_DCE_TRANSFORM(*xfm));
525 *xfm = NULL;
526 }
527
528 static 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
547 static 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
566 struct 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
592 static 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
612 struct 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
635 void 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
657 static 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) {
703 dal_display_clock_destroy(&pool->base.display_clock);
704 }
705
706 if (pool->base.irqs != NULL) {
707 dal_irq_service_destroy(&pool->base.irqs);
708 }
709 }
710
711
712 static void get_pixel_clock_parameters(
713 const struct pipe_ctx *pipe_ctx,
714 struct pixel_clk_params *pixel_clk_params)
715 {
716 const struct core_stream *stream = pipe_ctx->stream;
717
718 /*TODO: is this halved for YCbCr 420? in that case we might want to move
719 * the pixel clock normalization for hdmi up to here instead of doing it
720 * in pll_adjust_pix_clk
721 */
722 pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
723 pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
724 pixel_clk_params->signal_type = pipe_ctx->stream->signal;
725 pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1;
726 /* TODO: un-hardcode*/
727 pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
728 LINK_RATE_REF_FREQ_IN_KHZ;
729 pixel_clk_params->flags.ENABLE_SS = 0;
730 pixel_clk_params->color_depth =
731 stream->public.timing.display_color_depth;
732 pixel_clk_params->flags.DISPLAY_BLANKED = 1;
733 pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding ==
734 PIXEL_ENCODING_YCBCR420);
735 }
736
737 void dce110_resource_build_bit_depth_reduction_params(
738 const struct core_stream *stream,
739 struct bit_depth_reduction_params *fmt_bit_depth)
740 {
741 memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
742
743 /*TODO: Need to un-hardcode, refer to function with same name
744 * in dal2 hw_sequencer*/
745
746 fmt_bit_depth->flags.TRUNCATE_ENABLED = 0;
747 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0;
748 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0;
749
750 /* Diagnostics need consistent CRC of the image, that means
751 * dithering should not be enabled for Diagnostics. */
752 if (IS_DIAG_DC(stream->ctx->dce_environment) == false) {
753 switch (stream->public.timing.display_color_depth) {
754 case COLOR_DEPTH_666:
755 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
756 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
757 break;
758 case COLOR_DEPTH_888:
759 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
760 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
761 break;
762 case COLOR_DEPTH_101010:
763 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
764 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
765 break;
766 default:
767 break;
768 }
769 fmt_bit_depth->flags.RGB_RANDOM = 1;
770 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
771 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
772 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
773 }
774
775 return;
776 }
777
778 enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
779 {
780 get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params);
781 pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
782 pipe_ctx->clock_source,
783 &pipe_ctx->pix_clk_params,
784 &pipe_ctx->pll_settings);
785 dce110_resource_build_bit_depth_reduction_params(pipe_ctx->stream,
786 &pipe_ctx->stream->bit_depth_params);
787 pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding;
788
789 return DC_OK;
790 }
791
792 static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx)
793 {
794 if (pipe_ctx->pipe_idx != underlay_idx)
795 return true;
796 if (!pipe_ctx->surface)
797 return false;
798 if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
799 return false;
800 return true;
801 }
802
803 static enum dc_status validate_mapped_resource(
804 const struct core_dc *dc,
805 struct validate_context *context)
806 {
807 enum dc_status status = DC_OK;
808 uint8_t i, j, k;
809
810 for (i = 0; i < context->target_count; i++) {
811 struct core_target *target = context->targets[i];
812
813 for (j = 0; j < target->public.stream_count; j++) {
814 struct core_stream *stream =
815 DC_STREAM_TO_CORE(target->public.streams[j]);
816 struct core_link *link = stream->sink->link;
817
818 if (resource_is_stream_unchanged(dc->current_context, stream))
819 continue;
820
821 for (k = 0; k < MAX_PIPES; k++) {
822 struct pipe_ctx *pipe_ctx =
823 &context->res_ctx.pipe_ctx[k];
824
825 if (context->res_ctx.pipe_ctx[k].stream != stream)
826 continue;
827
828 if (!is_surface_pixel_format_supported(pipe_ctx,
829 context->res_ctx.pool->underlay_pipe_index))
830 return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED;
831
832 if (!pipe_ctx->tg->funcs->validate_timing(
833 pipe_ctx->tg, &stream->public.timing))
834 return DC_FAIL_CONTROLLER_VALIDATE;
835
836 status = dce110_resource_build_pipe_hw_param(pipe_ctx);
837
838 if (status != DC_OK)
839 return status;
840
841 if (!link->link_enc->funcs->validate_output_with_stream(
842 link->link_enc,
843 pipe_ctx))
844 return DC_FAIL_ENC_VALIDATE;
845
846 /* TODO: validate audio ASIC caps, encoder */
847
848 status = dc_link_validate_mode_timing(stream,
849 link,
850 &stream->public.timing);
851
852 if (status != DC_OK)
853 return status;
854
855 resource_build_info_frame(pipe_ctx);
856
857 /* do not need to validate non root pipes */
858 break;
859 }
860 }
861 }
862
863 return DC_OK;
864 }
865
866 enum dc_status dce110_validate_bandwidth(
867 const struct core_dc *dc,
868 struct validate_context *context)
869 {
870 enum dc_status result = DC_ERROR_UNEXPECTED;
871
872 dm_logger_write(
873 dc->ctx->logger, LOG_BANDWIDTH_CALCS,
874 "%s: start",
875 __func__);
876
877 if (!bw_calcs(
878 dc->ctx,
879 &dc->bw_dceip,
880 &dc->bw_vbios,
881 context->res_ctx.pipe_ctx,
882 context->res_ctx.pool->pipe_count,
883 &context->bw_results))
884 result = DC_FAIL_BANDWIDTH_VALIDATE;
885 else
886 result = DC_OK;
887
888 if (result == DC_FAIL_BANDWIDTH_VALIDATE)
889 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION,
890 "%s: %dx%d@%d Bandwidth validation failed!\n",
891 __func__,
892 context->targets[0]->public.streams[0]->timing.h_addressable,
893 context->targets[0]->public.streams[0]->timing.v_addressable,
894 context->targets[0]->public.streams[0]->timing.pix_clk_khz);
895
896 if (memcmp(&dc->current_context->bw_results,
897 &context->bw_results, sizeof(context->bw_results))) {
898 struct log_entry log_entry;
899 dm_logger_open(
900 dc->ctx->logger,
901 &log_entry,
902 LOG_BANDWIDTH_CALCS);
903 dm_logger_append(&log_entry, "%s: finish,\n"
904 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
905 "stutMark_b: %d stutMark_a: %d\n",
906 __func__,
907 context->bw_results.nbp_state_change_wm_ns[0].b_mark,
908 context->bw_results.nbp_state_change_wm_ns[0].a_mark,
909 context->bw_results.urgent_wm_ns[0].b_mark,
910 context->bw_results.urgent_wm_ns[0].a_mark,
911 context->bw_results.stutter_exit_wm_ns[0].b_mark,
912 context->bw_results.stutter_exit_wm_ns[0].a_mark);
913 dm_logger_append(&log_entry,
914 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
915 "stutMark_b: %d stutMark_a: %d\n",
916 context->bw_results.nbp_state_change_wm_ns[1].b_mark,
917 context->bw_results.nbp_state_change_wm_ns[1].a_mark,
918 context->bw_results.urgent_wm_ns[1].b_mark,
919 context->bw_results.urgent_wm_ns[1].a_mark,
920 context->bw_results.stutter_exit_wm_ns[1].b_mark,
921 context->bw_results.stutter_exit_wm_ns[1].a_mark);
922 dm_logger_append(&log_entry,
923 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
924 "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n",
925 context->bw_results.nbp_state_change_wm_ns[2].b_mark,
926 context->bw_results.nbp_state_change_wm_ns[2].a_mark,
927 context->bw_results.urgent_wm_ns[2].b_mark,
928 context->bw_results.urgent_wm_ns[2].a_mark,
929 context->bw_results.stutter_exit_wm_ns[2].b_mark,
930 context->bw_results.stutter_exit_wm_ns[2].a_mark,
931 context->bw_results.stutter_mode_enable);
932 dm_logger_append(&log_entry,
933 "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n"
934 "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n",
935 context->bw_results.cpuc_state_change_enable,
936 context->bw_results.cpup_state_change_enable,
937 context->bw_results.nbp_state_change_enable,
938 context->bw_results.all_displays_in_sync,
939 context->bw_results.dispclk_khz,
940 context->bw_results.required_sclk,
941 context->bw_results.required_sclk_deep_sleep,
942 context->bw_results.required_yclk,
943 context->bw_results.blackout_recovery_time_us);
944 dm_logger_close(&log_entry);
945 }
946 return result;
947 }
948
949 static bool dce110_validate_surface_sets(
950 const struct dc_validation_set set[],
951 int set_count)
952 {
953 int i;
954
955 for (i = 0; i < set_count; i++) {
956 if (set[i].surface_count == 0)
957 continue;
958
959 if (set[i].surface_count > 2)
960 return false;
961
962 if (set[i].surfaces[0]->src_rect.width
963 != set[i].target->streams[0]->src.width
964 || set[i].surfaces[0]->src_rect.height
965 != set[i].target->streams[0]->src.height)
966 return false;
967 if (set[i].surfaces[0]->format
968 >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
969 return false;
970
971 if (set[i].surface_count == 2) {
972 if (set[i].surfaces[1]->format
973 < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
974 return false;
975 if (set[i].surfaces[1]->src_rect.width > 1920
976 || set[i].surfaces[1]->src_rect.height > 1080)
977 return false;
978
979 if (set[i].target->streams[0]->timing.pixel_encoding != PIXEL_ENCODING_RGB)
980 return false;
981 }
982 }
983
984 return true;
985 }
986
987 enum dc_status dce110_validate_with_context(
988 const struct core_dc *dc,
989 const struct dc_validation_set set[],
990 int set_count,
991 struct validate_context *context)
992 {
993 struct dc_context *dc_ctx = dc->ctx;
994 enum dc_status result = DC_ERROR_UNEXPECTED;
995 int i;
996
997 if (!dce110_validate_surface_sets(set, set_count))
998 return DC_FAIL_SURFACE_VALIDATE;
999
1000 context->res_ctx.pool = dc->res_pool;
1001
1002 for (i = 0; i < set_count; i++) {
1003 context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
1004 dc_target_retain(&context->targets[i]->public);
1005 context->target_count++;
1006 }
1007
1008 result = resource_map_pool_resources(dc, context);
1009
1010 if (result == DC_OK)
1011 result = resource_map_clock_resources(dc, context);
1012
1013 if (!resource_validate_attach_surfaces(
1014 set, set_count, dc->current_context, context)) {
1015 DC_ERROR("Failed to attach surface to target!\n");
1016 return DC_FAIL_ATTACH_SURFACES;
1017 }
1018
1019 if (result == DC_OK)
1020 result = validate_mapped_resource(dc, context);
1021
1022 if (result == DC_OK)
1023 result = resource_build_scaling_params_for_context(dc, context);
1024
1025 if (result == DC_OK)
1026 result = dce110_validate_bandwidth(dc, context);
1027
1028 return result;
1029 }
1030
1031 enum dc_status dce110_validate_guaranteed(
1032 const struct core_dc *dc,
1033 const struct dc_target *dc_target,
1034 struct validate_context *context)
1035 {
1036 enum dc_status result = DC_ERROR_UNEXPECTED;
1037
1038 context->res_ctx.pool = dc->res_pool;
1039
1040 context->targets[0] = DC_TARGET_TO_CORE(dc_target);
1041 dc_target_retain(&context->targets[0]->public);
1042 context->target_count++;
1043
1044 result = resource_map_pool_resources(dc, context);
1045
1046 if (result == DC_OK)
1047 result = resource_map_clock_resources(dc, context);
1048
1049 if (result == DC_OK)
1050 result = validate_mapped_resource(dc, context);
1051
1052 if (result == DC_OK) {
1053 validate_guaranteed_copy_target(
1054 context, dc->public.caps.max_targets);
1055 result = resource_build_scaling_params_for_context(dc, context);
1056 }
1057
1058 if (result == DC_OK)
1059 result = dce110_validate_bandwidth(dc, context);
1060
1061 return result;
1062 }
1063
1064 static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer(
1065 struct resource_context *res_ctx,
1066 struct core_stream *stream)
1067 {
1068 unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index;
1069 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx];
1070
1071 if (res_ctx->pipe_ctx[underlay_idx].stream) {
1072 return NULL;
1073 }
1074
1075 pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx];
1076 pipe_ctx->mi = res_ctx->pool->mis[underlay_idx];
1077 /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/
1078 pipe_ctx->xfm = res_ctx->pool->transforms[underlay_idx];
1079 pipe_ctx->opp = res_ctx->pool->opps[underlay_idx];
1080 pipe_ctx->dis_clk = res_ctx->pool->display_clock;
1081 pipe_ctx->pipe_idx = underlay_idx;
1082
1083 pipe_ctx->stream = stream;
1084
1085 return pipe_ctx;
1086
1087 }
1088
1089 static void dce110_destroy_resource_pool(struct resource_pool **pool)
1090 {
1091 struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
1092
1093 destruct(dce110_pool);
1094 dm_free(dce110_pool);
1095 *pool = NULL;
1096 }
1097
1098
1099 static const struct resource_funcs dce110_res_pool_funcs = {
1100 .destroy = dce110_destroy_resource_pool,
1101 .link_enc_create = dce110_link_encoder_create,
1102 .validate_with_context = dce110_validate_with_context,
1103 .validate_guaranteed = dce110_validate_guaranteed,
1104 .validate_bandwidth = dce110_validate_bandwidth,
1105 .acquire_idle_pipe_for_layer = dce110_acquire_idle_pipe_for_layer,
1106 .build_bit_depth_reduction_params =
1107 dce110_resource_build_bit_depth_reduction_params
1108 };
1109
1110 static void underlay_create(struct dc_context *ctx, struct resource_pool *pool)
1111 {
1112 struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv));
1113 struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv));
1114 struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv));
1115 struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv));
1116
1117 dce110_opp_v_construct(dce110_oppv, ctx);
1118 dce110_timing_generator_v_construct(dce110_tgv, ctx);
1119 dce110_mem_input_v_construct(dce110_miv, ctx);
1120 dce110_transform_v_construct(dce110_xfmv, ctx);
1121
1122 pool->opps[pool->pipe_count] = &dce110_oppv->base;
1123 pool->timing_generators[pool->pipe_count] = &dce110_tgv->base;
1124 pool->mis[pool->pipe_count] = &dce110_miv->base;
1125 pool->transforms[pool->pipe_count] = &dce110_xfmv->base;
1126 pool->pipe_count++;
1127
1128 /* update the public caps to indicate an underlay is available */
1129 ctx->dc->caps.max_slave_planes = 1;
1130 ctx->dc->caps.max_slave_planes = 1;
1131 }
1132
1133 static void bw_calcs_data_update_from_pplib(struct core_dc *dc)
1134 {
1135 struct dm_pp_clock_levels clks = {0};
1136
1137 /*do system clock*/
1138 dm_pp_get_clock_levels_by_type(
1139 dc->ctx,
1140 DM_PP_CLOCK_TYPE_ENGINE_CLK,
1141 &clks);
1142 /* convert all the clock fro kHz to fix point mHz */
1143 dc->bw_vbios.high_sclk = bw_frc_to_fixed(
1144 clks.clocks_in_khz[clks.num_levels-1], 1000);
1145 dc->bw_vbios.mid1_sclk = bw_frc_to_fixed(
1146 clks.clocks_in_khz[clks.num_levels/8], 1000);
1147 dc->bw_vbios.mid2_sclk = bw_frc_to_fixed(
1148 clks.clocks_in_khz[clks.num_levels*2/8], 1000);
1149 dc->bw_vbios.mid3_sclk = bw_frc_to_fixed(
1150 clks.clocks_in_khz[clks.num_levels*3/8], 1000);
1151 dc->bw_vbios.mid4_sclk = bw_frc_to_fixed(
1152 clks.clocks_in_khz[clks.num_levels*4/8], 1000);
1153 dc->bw_vbios.mid5_sclk = bw_frc_to_fixed(
1154 clks.clocks_in_khz[clks.num_levels*5/8], 1000);
1155 dc->bw_vbios.mid6_sclk = bw_frc_to_fixed(
1156 clks.clocks_in_khz[clks.num_levels*6/8], 1000);
1157 dc->bw_vbios.low_sclk = bw_frc_to_fixed(
1158 clks.clocks_in_khz[0], 1000);
1159 dc->sclk_lvls = clks;
1160
1161 /*do display clock*/
1162 dm_pp_get_clock_levels_by_type(
1163 dc->ctx,
1164 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
1165 &clks);
1166 dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed(
1167 clks.clocks_in_khz[clks.num_levels-1], 1000);
1168 dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed(
1169 clks.clocks_in_khz[clks.num_levels>>1], 1000);
1170 dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed(
1171 clks.clocks_in_khz[0], 1000);
1172
1173 /*do memory clock*/
1174 dm_pp_get_clock_levels_by_type(
1175 dc->ctx,
1176 DM_PP_CLOCK_TYPE_MEMORY_CLK,
1177 &clks);
1178
1179 dc->bw_vbios.low_yclk = bw_frc_to_fixed(
1180 clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000);
1181 dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
1182 clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER,
1183 1000);
1184 dc->bw_vbios.high_yclk = bw_frc_to_fixed(
1185 clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER,
1186 1000);
1187 }
1188
1189 enum clocks_state dce110_resource_convert_clock_state_pp_to_dc(
1190 enum dm_pp_clocks_state pp_clock_state)
1191 {
1192 enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID;
1193
1194 switch (pp_clock_state) {
1195 case DM_PP_CLOCKS_STATE_INVALID:
1196 dc_clocks_state = CLOCKS_STATE_INVALID;
1197 break;
1198 case DM_PP_CLOCKS_STATE_ULTRA_LOW:
1199 dc_clocks_state = CLOCKS_STATE_ULTRA_LOW;
1200 break;
1201 case DM_PP_CLOCKS_STATE_LOW:
1202 dc_clocks_state = CLOCKS_STATE_LOW;
1203 break;
1204 case DM_PP_CLOCKS_STATE_NOMINAL:
1205 dc_clocks_state = CLOCKS_STATE_NOMINAL;
1206 break;
1207 case DM_PP_CLOCKS_STATE_PERFORMANCE:
1208 dc_clocks_state = CLOCKS_STATE_PERFORMANCE;
1209 break;
1210 case DM_PP_CLOCKS_DPM_STATE_LEVEL_4:
1211 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4;
1212 break;
1213 case DM_PP_CLOCKS_DPM_STATE_LEVEL_5:
1214 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5;
1215 break;
1216 case DM_PP_CLOCKS_DPM_STATE_LEVEL_6:
1217 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6;
1218 break;
1219 case DM_PP_CLOCKS_DPM_STATE_LEVEL_7:
1220 dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7;
1221 break;
1222 default:
1223 dc_clocks_state = CLOCKS_STATE_INVALID;
1224 break;
1225 }
1226
1227 return dc_clocks_state;
1228 }
1229
1230 const struct resource_caps *dce110_resource_cap(
1231 struct hw_asic_id *asic_id)
1232 {
1233 if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev))
1234 return &stoney_resource_cap;
1235 else
1236 return &carrizo_resource_cap;
1237 }
1238
1239 static bool construct(
1240 uint8_t num_virtual_links,
1241 struct core_dc *dc,
1242 struct dce110_resource_pool *pool,
1243 struct hw_asic_id asic_id)
1244 {
1245 unsigned int i;
1246 struct dc_context *ctx = dc->ctx;
1247 struct firmware_info info;
1248 struct dc_bios *bp;
1249 struct dm_pp_static_clock_info static_clk_info = {0};
1250
1251 ctx->dc_bios->regs = &bios_regs;
1252
1253 pool->base.res_cap = dce110_resource_cap(&ctx->asic_id);
1254 pool->base.funcs = &dce110_res_pool_funcs;
1255
1256 /*************************************************
1257 * Resource + asic cap harcoding *
1258 *************************************************/
1259
1260 pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
1261 pool->base.underlay_pipe_index = pool->base.pipe_count;
1262
1263 dc->public.caps.max_downscale_ratio = 150;
1264 dc->public.caps.i2c_speed_in_khz = 100;
1265
1266 /*************************************************
1267 * Create resources *
1268 *************************************************/
1269
1270 bp = ctx->dc_bios;
1271
1272 if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) &&
1273 info.external_clock_source_frequency_for_dp != 0) {
1274 pool->base.dp_clock_source =
1275 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
1276
1277 pool->base.clock_sources[0] =
1278 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0,
1279 &clk_src_regs[0], false);
1280 pool->base.clock_sources[1] =
1281 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1,
1282 &clk_src_regs[1], false);
1283
1284 pool->base.clk_src_count = 2;
1285
1286 /* TODO: find out if CZ support 3 PLLs */
1287 }
1288
1289 if (pool->base.dp_clock_source == NULL) {
1290 dm_error("DC: failed to create dp clock source!\n");
1291 BREAK_TO_DEBUGGER();
1292 goto res_create_fail;
1293 }
1294
1295 for (i = 0; i < pool->base.clk_src_count; i++) {
1296 if (pool->base.clock_sources[i] == NULL) {
1297 dm_error("DC: failed to create clock sources!\n");
1298 BREAK_TO_DEBUGGER();
1299 goto res_create_fail;
1300 }
1301 }
1302
1303 pool->base.display_clock = dal_display_clock_dce110_create(ctx);
1304 if (pool->base.display_clock == NULL) {
1305 dm_error("DC: failed to create display clock!\n");
1306 BREAK_TO_DEBUGGER();
1307 goto res_create_fail;
1308 }
1309
1310 /* get static clock information for PPLIB or firmware, save
1311 * max_clock_state
1312 */
1313 if (dm_pp_get_static_clocks(ctx, &static_clk_info)) {
1314 enum clocks_state max_clocks_state =
1315 dce110_resource_convert_clock_state_pp_to_dc(
1316 static_clk_info.max_clocks_state);
1317
1318 pool->base.display_clock->funcs->store_max_clocks_state(
1319 pool->base.display_clock, max_clocks_state);
1320 }
1321
1322 {
1323 struct irq_service_init_data init_data;
1324 init_data.ctx = dc->ctx;
1325 pool->base.irqs = dal_irq_service_dce110_create(&init_data);
1326 if (!pool->base.irqs)
1327 goto res_create_fail;
1328 }
1329
1330 for (i = 0; i < pool->base.pipe_count; i++) {
1331 pool->base.timing_generators[i] = dce110_timing_generator_create(
1332 ctx, i, &dce110_tg_offsets[i]);
1333 if (pool->base.timing_generators[i] == NULL) {
1334 BREAK_TO_DEBUGGER();
1335 dm_error("DC: failed to create tg!\n");
1336 goto res_create_fail;
1337 }
1338
1339 pool->base.mis[i] = dce110_mem_input_create(ctx, i,
1340 &dce110_mi_reg_offsets[i]);
1341 if (pool->base.mis[i] == NULL) {
1342 BREAK_TO_DEBUGGER();
1343 dm_error(
1344 "DC: failed to create memory input!\n");
1345 goto res_create_fail;
1346 }
1347
1348 pool->base.ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]);
1349 if (pool->base.ipps[i] == NULL) {
1350 BREAK_TO_DEBUGGER();
1351 dm_error(
1352 "DC: failed to create input pixel processor!\n");
1353 goto res_create_fail;
1354 }
1355
1356 pool->base.transforms[i] = dce110_transform_create(ctx, i);
1357 if (pool->base.transforms[i] == NULL) {
1358 BREAK_TO_DEBUGGER();
1359 dm_error(
1360 "DC: failed to create transform!\n");
1361 goto res_create_fail;
1362 }
1363
1364 pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]);
1365 if (pool->base.opps[i] == NULL) {
1366 BREAK_TO_DEBUGGER();
1367 dm_error(
1368 "DC: failed to create output pixel processor!\n");
1369 goto res_create_fail;
1370 }
1371 }
1372
1373 underlay_create(ctx, &pool->base);
1374
1375 if (!resource_construct(num_virtual_links, dc, &pool->base,
1376 &res_create_funcs))
1377 goto res_create_fail;
1378
1379 /* Create hardware sequencer */
1380 if (!dce110_hw_sequencer_construct(dc))
1381 goto res_create_fail;
1382
1383 if (ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev))
1384 bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_STONEY);
1385 else
1386 bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_CARRIZO);
1387
1388 bw_calcs_data_update_from_pplib(dc);
1389
1390 return true;
1391
1392 res_create_fail:
1393 destruct(pool);
1394 return false;
1395 }
1396
1397 struct resource_pool *dce110_create_resource_pool(
1398 uint8_t num_virtual_links,
1399 struct core_dc *dc,
1400 struct hw_asic_id asic_id)
1401 {
1402 struct dce110_resource_pool *pool =
1403 dm_alloc(sizeof(struct dce110_resource_pool));
1404
1405 if (!pool)
1406 return NULL;
1407
1408 if (construct(num_virtual_links, dc, pool, asic_id))
1409 return &pool->base;
1410
1411 BREAK_TO_DEBUGGER();
1412 return NULL;
1413 }