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