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