1/* $NetBSD: amdgpu_dce120_resource.c,v 1.4 2021/12/19 11:59:31 riastradh Exp $ */ 2 3/* 4* Copyright 2012-15 Advanced Micro Devices, Inc.cls 5* 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: AMD 26 * 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: amdgpu_dce120_resource.c,v 1.4 2021/12/19 11:59:31 riastradh Exp $"); 31 32#include <linux/slab.h> 33 34#include "dm_services.h" 35 36 37#include "stream_encoder.h" 38#include "resource.h" 39#include "include/irq_service_interface.h" 40#include "dce120_resource.h" 41 42#include "dce112/dce112_resource.h" 43 44#include "dce110/dce110_resource.h" 45#include "../virtual/virtual_stream_encoder.h" 46#include "dce120_timing_generator.h" 47#include "irq/dce120/irq_service_dce120.h" 48#include "dce/dce_opp.h" 49#include "dce/dce_clock_source.h" 50#include "dce/dce_ipp.h" 51#include "dce/dce_mem_input.h" 52 53#include "dce110/dce110_hw_sequencer.h" 54#include "dce120/dce120_hw_sequencer.h" 55#include "dce/dce_transform.h" 56#include "clk_mgr.h" 57#include "dce/dce_audio.h" 58#include "dce/dce_link_encoder.h" 59#include "dce/dce_stream_encoder.h" 60#include "dce/dce_hwseq.h" 61#include "dce/dce_abm.h" 62#include "dce/dce_dmcu.h" 63#include "dce/dce_aux.h" 64#include "dce/dce_i2c.h" 65 66#include "dce/dce_12_0_offset.h" 67#include "dce/dce_12_0_sh_mask.h" 68#include "soc15_hw_ip.h" 69#include "vega10_ip_offset.h" 70#include "nbio/nbio_6_1_offset.h" 71#include "mmhub/mmhub_1_0_offset.h" 72#include "mmhub/mmhub_1_0_sh_mask.h" 73#include "reg_helper.h" 74 75#include "dce100/dce100_resource.h" 76 77#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL 78 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f 79 #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 80 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f 81 #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 82 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f 83 #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 84 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f 85 #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 86 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f 87 #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 88 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f 89 #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 90 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f 91 #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 92#endif 93 94enum dce120_clk_src_array_id { 95 DCE120_CLK_SRC_PLL0, 96 DCE120_CLK_SRC_PLL1, 97 DCE120_CLK_SRC_PLL2, 98 DCE120_CLK_SRC_PLL3, 99 DCE120_CLK_SRC_PLL4, 100 DCE120_CLK_SRC_PLL5, 101 102 DCE120_CLK_SRC_TOTAL 103}; 104 105static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { 106 { 107 .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), 108 }, 109 { 110 .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), 111 }, 112 { 113 .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), 114 }, 115 { 116 .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), 117 }, 118 { 119 .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), 120 }, 121 { 122 .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), 123 } 124}; 125 126/* begin ********************* 127 * macros to expend register list macro defined in HW object header file */ 128 129#define BASE_INNER(seg) \ 130 DCE_BASE__INST0_SEG ## seg 131 132#define NBIO_BASE_INNER(seg) \ 133 NBIF_BASE__INST0_SEG ## seg 134 135#define NBIO_BASE(seg) \ 136 NBIO_BASE_INNER(seg) 137 138/* compile time expand base address. */ 139#define BASE(seg) \ 140 BASE_INNER(seg) 141 142#define SR(reg_name)\ 143 .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ 144 mm ## reg_name 145 146#define SRI(reg_name, block, id)\ 147 .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ 148 mm ## block ## id ## _ ## reg_name 149 150/* MMHUB */ 151#define MMHUB_BASE_INNER(seg) \ 152 MMHUB_BASE__INST0_SEG ## seg 153 154#define MMHUB_BASE(seg) \ 155 MMHUB_BASE_INNER(seg) 156 157#define MMHUB_SR(reg_name)\ 158 .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ 159 mm ## reg_name 160 161/* macros to expend register list macro defined in HW object header file 162 * end *********************/ 163 164 165static const struct dce_dmcu_registers dmcu_regs = { 166 DMCU_DCE110_COMMON_REG_LIST() 167}; 168 169static const struct dce_dmcu_shift dmcu_shift = { 170 DMCU_MASK_SH_LIST_DCE110(__SHIFT) 171}; 172 173static const struct dce_dmcu_mask dmcu_mask = { 174 DMCU_MASK_SH_LIST_DCE110(_MASK) 175}; 176 177static const struct dce_abm_registers abm_regs = { 178 ABM_DCE110_COMMON_REG_LIST() 179}; 180 181static const struct dce_abm_shift abm_shift = { 182 ABM_MASK_SH_LIST_DCE110(__SHIFT) 183}; 184 185static const struct dce_abm_mask abm_mask = { 186 ABM_MASK_SH_LIST_DCE110(_MASK) 187}; 188 189#define ipp_regs(id)\ 190[id] = {\ 191 IPP_DCE110_REG_LIST_DCE_BASE(id)\ 192} 193 194static const struct dce_ipp_registers ipp_regs[] = { 195 ipp_regs(0), 196 ipp_regs(1), 197 ipp_regs(2), 198 ipp_regs(3), 199 ipp_regs(4), 200 ipp_regs(5) 201}; 202 203static const struct dce_ipp_shift ipp_shift = { 204 IPP_DCE120_MASK_SH_LIST_SOC_BASE(__SHIFT) 205}; 206 207static const struct dce_ipp_mask ipp_mask = { 208 IPP_DCE120_MASK_SH_LIST_SOC_BASE(_MASK) 209}; 210 211#define transform_regs(id)\ 212[id] = {\ 213 XFM_COMMON_REG_LIST_DCE110(id)\ 214} 215 216static const struct dce_transform_registers xfm_regs[] = { 217 transform_regs(0), 218 transform_regs(1), 219 transform_regs(2), 220 transform_regs(3), 221 transform_regs(4), 222 transform_regs(5) 223}; 224 225static const struct dce_transform_shift xfm_shift = { 226 XFM_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) 227}; 228 229static const struct dce_transform_mask xfm_mask = { 230 XFM_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) 231}; 232 233#define aux_regs(id)\ 234[id] = {\ 235 AUX_REG_LIST(id)\ 236} 237 238static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { 239 aux_regs(0), 240 aux_regs(1), 241 aux_regs(2), 242 aux_regs(3), 243 aux_regs(4), 244 aux_regs(5) 245}; 246 247#define hpd_regs(id)\ 248[id] = {\ 249 HPD_REG_LIST(id)\ 250} 251 252static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { 253 hpd_regs(0), 254 hpd_regs(1), 255 hpd_regs(2), 256 hpd_regs(3), 257 hpd_regs(4), 258 hpd_regs(5) 259}; 260 261#define link_regs(id)\ 262[id] = {\ 263 LE_DCE120_REG_LIST(id), \ 264 SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ 265} 266 267static const struct dce110_link_enc_registers link_enc_regs[] = { 268 link_regs(0), 269 link_regs(1), 270 link_regs(2), 271 link_regs(3), 272 link_regs(4), 273 link_regs(5), 274 link_regs(6), 275}; 276 277 278#define stream_enc_regs(id)\ 279[id] = {\ 280 SE_COMMON_REG_LIST(id),\ 281 .TMDS_CNTL = 0,\ 282} 283 284static const struct dce110_stream_enc_registers stream_enc_regs[] = { 285 stream_enc_regs(0), 286 stream_enc_regs(1), 287 stream_enc_regs(2), 288 stream_enc_regs(3), 289 stream_enc_regs(4), 290 stream_enc_regs(5) 291}; 292 293static const struct dce_stream_encoder_shift se_shift = { 294 SE_COMMON_MASK_SH_LIST_DCE120(__SHIFT) 295}; 296 297static const struct dce_stream_encoder_mask se_mask = { 298 SE_COMMON_MASK_SH_LIST_DCE120(_MASK) 299}; 300 301static const struct dce110_aux_registers_shift aux_shift = { 302 DCE12_AUX_MASK_SH_LIST(__SHIFT) 303}; 304 305static const struct dce110_aux_registers_mask aux_mask = { 306 DCE12_AUX_MASK_SH_LIST(_MASK) 307}; 308 309#define opp_regs(id)\ 310[id] = {\ 311 OPP_DCE_120_REG_LIST(id),\ 312} 313 314static const struct dce_opp_registers opp_regs[] = { 315 opp_regs(0), 316 opp_regs(1), 317 opp_regs(2), 318 opp_regs(3), 319 opp_regs(4), 320 opp_regs(5) 321}; 322 323static const struct dce_opp_shift opp_shift = { 324 OPP_COMMON_MASK_SH_LIST_DCE_120(__SHIFT) 325}; 326 327static const struct dce_opp_mask opp_mask = { 328 OPP_COMMON_MASK_SH_LIST_DCE_120(_MASK) 329}; 330 #define aux_engine_regs(id)\ 331[id] = {\ 332 AUX_COMMON_REG_LIST(id), \ 333 .AUX_RESET_MASK = 0 \ 334} 335 336static const struct dce110_aux_registers aux_engine_regs[] = { 337 aux_engine_regs(0), 338 aux_engine_regs(1), 339 aux_engine_regs(2), 340 aux_engine_regs(3), 341 aux_engine_regs(4), 342 aux_engine_regs(5) 343}; 344 345#define audio_regs(id)\ 346[id] = {\ 347 AUD_COMMON_REG_LIST(id)\ 348} 349 350static const struct dce_audio_registers audio_regs[] = { 351 audio_regs(0), 352 audio_regs(1), 353 audio_regs(2), 354 audio_regs(3), 355 audio_regs(4), 356 audio_regs(5) 357}; 358 359#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ 360 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ 361 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ 362 AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) 363 364static const struct dce_audio_shift audio_shift = { 365 DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) 366}; 367 368static const struct dce_audio_mask audio_mask = { 369 DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) 370}; 371 372static int map_transmitter_id_to_phy_instance( 373 enum transmitter transmitter) 374{ 375 switch (transmitter) { 376 case TRANSMITTER_UNIPHY_A: 377 return 0; 378 break; 379 case TRANSMITTER_UNIPHY_B: 380 return 1; 381 break; 382 case TRANSMITTER_UNIPHY_C: 383 return 2; 384 break; 385 case TRANSMITTER_UNIPHY_D: 386 return 3; 387 break; 388 case TRANSMITTER_UNIPHY_E: 389 return 4; 390 break; 391 case TRANSMITTER_UNIPHY_F: 392 return 5; 393 break; 394 case TRANSMITTER_UNIPHY_G: 395 return 6; 396 break; 397 default: 398 ASSERT(0); 399 return 0; 400 } 401} 402 403#define clk_src_regs(index, id)\ 404[index] = {\ 405 CS_COMMON_REG_LIST_DCE_112(id),\ 406} 407 408static const struct dce110_clk_src_regs clk_src_regs[] = { 409 clk_src_regs(0, A), 410 clk_src_regs(1, B), 411 clk_src_regs(2, C), 412 clk_src_regs(3, D), 413 clk_src_regs(4, E), 414 clk_src_regs(5, F) 415}; 416 417static const struct dce110_clk_src_shift cs_shift = { 418 CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) 419}; 420 421static const struct dce110_clk_src_mask cs_mask = { 422 CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) 423}; 424 425struct output_pixel_processor *dce120_opp_create( 426 struct dc_context *ctx, 427 uint32_t inst) 428{ 429 struct dce110_opp *opp = 430 kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); 431 432 if (!opp) 433 return NULL; 434 435 dce110_opp_construct(opp, 436 ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); 437 return &opp->base; 438} 439struct dce_aux *dce120_aux_engine_create( 440 struct dc_context *ctx, 441 uint32_t inst) 442{ 443 struct aux_engine_dce110 *aux_engine = 444 kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); 445 446 if (!aux_engine) 447 return NULL; 448 449 dce110_aux_engine_construct(aux_engine, ctx, inst, 450 SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, 451 &aux_engine_regs[inst], 452 &aux_mask, 453 &aux_shift, 454 ctx->dc->caps.extended_aux_timeout_support); 455 456 return &aux_engine->base; 457} 458#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } 459 460static const struct dce_i2c_registers i2c_hw_regs[] = { 461 i2c_inst_regs(1), 462 i2c_inst_regs(2), 463 i2c_inst_regs(3), 464 i2c_inst_regs(4), 465 i2c_inst_regs(5), 466 i2c_inst_regs(6), 467}; 468 469static const struct dce_i2c_shift i2c_shifts = { 470 I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) 471}; 472 473static const struct dce_i2c_mask i2c_masks = { 474 I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) 475}; 476 477struct dce_i2c_hw *dce120_i2c_hw_create( 478 struct dc_context *ctx, 479 uint32_t inst) 480{ 481 struct dce_i2c_hw *dce_i2c_hw = 482 kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); 483 484 if (!dce_i2c_hw) 485 return NULL; 486 487 dce112_i2c_hw_construct(dce_i2c_hw, ctx, inst, 488 &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); 489 490 return dce_i2c_hw; 491} 492static const struct bios_registers bios_regs = { 493 .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3 + NBIO_BASE(mmBIOS_SCRATCH_3_BASE_IDX), 494 .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) 495}; 496 497static const struct resource_caps res_cap = { 498 .num_timing_generator = 6, 499 .num_audio = 7, 500 .num_stream_encoder = 6, 501 .num_pll = 6, 502 .num_ddc = 6, 503}; 504 505static const struct dc_plane_cap plane_cap = { 506 .type = DC_PLANE_TYPE_DCE_RGB, 507 508 .pixel_format_support = { 509 .argb8888 = true, 510 .nv12 = false, 511 .fp16 = false 512 }, 513 514 .max_upscale_factor = { 515 .argb8888 = 16000, 516 .nv12 = 1, 517 .fp16 = 1 518 }, 519 520 .max_downscale_factor = { 521 .argb8888 = 250, 522 .nv12 = 1, 523 .fp16 = 1 524 } 525}; 526 527static const struct dc_debug_options debug_defaults = { 528 .disable_clock_gate = true, 529}; 530 531static struct clock_source *dce120_clock_source_create( 532 struct dc_context *ctx, 533 struct dc_bios *bios, 534 enum clock_source_id id, 535 const struct dce110_clk_src_regs *regs, 536 bool dp_clk_src) 537{ 538 struct dce110_clk_src *clk_src = 539 kzalloc(sizeof(*clk_src), GFP_KERNEL); 540 541 if (!clk_src) 542 return NULL; 543 544 if (dce112_clk_src_construct(clk_src, ctx, bios, id, 545 regs, &cs_shift, &cs_mask)) { 546 clk_src->base.dp_clk_src = dp_clk_src; 547 return &clk_src->base; 548 } 549 550 kfree(clk_src); 551 BREAK_TO_DEBUGGER(); 552 return NULL; 553} 554 555static void dce120_clock_source_destroy(struct clock_source **clk_src) 556{ 557 kfree(TO_DCE110_CLK_SRC(*clk_src)); 558 *clk_src = NULL; 559} 560 561 562static bool dce120_hw_sequencer_create(struct dc *dc) 563{ 564 /* All registers used by dce11.2 match those in dce11 in offset and 565 * structure 566 */ 567 dce120_hw_sequencer_construct(dc); 568 569 /*TODO Move to separate file and Override what is needed */ 570 571 return true; 572} 573 574static struct timing_generator *dce120_timing_generator_create( 575 struct dc_context *ctx, 576 uint32_t instance, 577 const struct dce110_timing_generator_offsets *offsets) 578{ 579 struct dce110_timing_generator *tg110 = 580 kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); 581 582 if (!tg110) 583 return NULL; 584 585 dce120_timing_generator_construct(tg110, ctx, instance, offsets); 586 return &tg110->base; 587} 588 589static void dce120_transform_destroy(struct transform **xfm) 590{ 591 kfree(TO_DCE_TRANSFORM(*xfm)); 592 *xfm = NULL; 593} 594 595static void dce120_resource_destruct(struct dce110_resource_pool *pool) 596{ 597 unsigned int i; 598 599 for (i = 0; i < pool->base.pipe_count; i++) { 600 if (pool->base.opps[i] != NULL) 601 dce110_opp_destroy(&pool->base.opps[i]); 602 603 if (pool->base.transforms[i] != NULL) 604 dce120_transform_destroy(&pool->base.transforms[i]); 605 606 if (pool->base.ipps[i] != NULL) 607 dce_ipp_destroy(&pool->base.ipps[i]); 608 609 if (pool->base.mis[i] != NULL) { 610 kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); 611 pool->base.mis[i] = NULL; 612 } 613 614 if (pool->base.irqs != NULL) { 615 dal_irq_service_destroy(&pool->base.irqs); 616 } 617 618 if (pool->base.timing_generators[i] != NULL) { 619 kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); 620 pool->base.timing_generators[i] = NULL; 621 } 622 } 623 624 for (i = 0; i < pool->base.res_cap->num_ddc; i++) { 625 if (pool->base.engines[i] != NULL) 626 dce110_engine_destroy(&pool->base.engines[i]); 627 if (pool->base.hw_i2cs[i] != NULL) { 628 kfree(pool->base.hw_i2cs[i]); 629 pool->base.hw_i2cs[i] = NULL; 630 } 631 if (pool->base.sw_i2cs[i] != NULL) { 632 kfree(pool->base.sw_i2cs[i]); 633 pool->base.sw_i2cs[i] = NULL; 634 } 635 } 636 637 for (i = 0; i < pool->base.audio_count; i++) { 638 if (pool->base.audios[i]) 639 dce_aud_destroy(&pool->base.audios[i]); 640 } 641 642 for (i = 0; i < pool->base.stream_enc_count; i++) { 643 if (pool->base.stream_enc[i] != NULL) 644 kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); 645 } 646 647 for (i = 0; i < pool->base.clk_src_count; i++) { 648 if (pool->base.clock_sources[i] != NULL) 649 dce120_clock_source_destroy( 650 &pool->base.clock_sources[i]); 651 } 652 653 if (pool->base.dp_clock_source != NULL) 654 dce120_clock_source_destroy(&pool->base.dp_clock_source); 655 656 if (pool->base.abm != NULL) 657 dce_abm_destroy(&pool->base.abm); 658 659 if (pool->base.dmcu != NULL) 660 dce_dmcu_destroy(&pool->base.dmcu); 661} 662 663static void read_dce_straps( 664 struct dc_context *ctx, 665 struct resource_straps *straps) 666{ 667 uint32_t reg_val = dm_read_reg_soc15(ctx, mmCC_DC_MISC_STRAPS, 0); 668 669 straps->audio_stream_number = get_reg_field_value(reg_val, 670 CC_DC_MISC_STRAPS, 671 AUDIO_STREAM_NUMBER); 672 straps->hdmi_disable = get_reg_field_value(reg_val, 673 CC_DC_MISC_STRAPS, 674 HDMI_DISABLE); 675 676 reg_val = dm_read_reg_soc15(ctx, mmDC_PINSTRAPS, 0); 677 straps->dc_pinstraps_audio = get_reg_field_value(reg_val, 678 DC_PINSTRAPS, 679 DC_PINSTRAPS_AUDIO); 680} 681 682static struct audio *create_audio( 683 struct dc_context *ctx, unsigned int inst) 684{ 685 return dce_audio_create(ctx, inst, 686 &audio_regs[inst], &audio_shift, &audio_mask); 687} 688 689static const struct encoder_feature_support link_enc_feature = { 690 .max_hdmi_deep_color = COLOR_DEPTH_121212, 691 .max_hdmi_pixel_clock = 600000, 692 .hdmi_ycbcr420_supported = true, 693 .dp_ycbcr420_supported = false, 694 .flags.bits.IS_HBR2_CAPABLE = true, 695 .flags.bits.IS_HBR3_CAPABLE = true, 696 .flags.bits.IS_TPS3_CAPABLE = true, 697 .flags.bits.IS_TPS4_CAPABLE = true, 698}; 699 700static struct link_encoder *dce120_link_encoder_create( 701 const struct encoder_init_data *enc_init_data) 702{ 703 struct dce110_link_encoder *enc110 = 704 kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); 705 int link_regs_id; 706 707 if (!enc110) 708 return NULL; 709 710 link_regs_id = 711 map_transmitter_id_to_phy_instance(enc_init_data->transmitter); 712 713 dce110_link_encoder_construct(enc110, 714 enc_init_data, 715 &link_enc_feature, 716 &link_enc_regs[link_regs_id], 717 &link_enc_aux_regs[enc_init_data->channel - 1], 718 &link_enc_hpd_regs[enc_init_data->hpd_source]); 719 720 return &enc110->base; 721} 722 723static struct input_pixel_processor *dce120_ipp_create( 724 struct dc_context *ctx, uint32_t inst) 725{ 726 struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); 727 728 if (!ipp) { 729 BREAK_TO_DEBUGGER(); 730 return NULL; 731 } 732 733 dce_ipp_construct(ipp, ctx, inst, 734 &ipp_regs[inst], &ipp_shift, &ipp_mask); 735 return &ipp->base; 736} 737 738static struct stream_encoder *dce120_stream_encoder_create( 739 enum engine_id eng_id, 740 struct dc_context *ctx) 741{ 742 struct dce110_stream_encoder *enc110 = 743 kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); 744 745 if (!enc110) 746 return NULL; 747 748 dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, 749 &stream_enc_regs[eng_id], 750 &se_shift, &se_mask); 751 return &enc110->base; 752} 753 754#define SRII(reg_name, block, id)\ 755 .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ 756 mm ## block ## id ## _ ## reg_name 757 758static const struct dce_hwseq_registers hwseq_reg = { 759 HWSEQ_DCE120_REG_LIST() 760}; 761 762static const struct dce_hwseq_shift hwseq_shift = { 763 HWSEQ_DCE12_MASK_SH_LIST(__SHIFT) 764}; 765 766static const struct dce_hwseq_mask hwseq_mask = { 767 HWSEQ_DCE12_MASK_SH_LIST(_MASK) 768}; 769 770/* HWSEQ regs for VG20 */ 771static const struct dce_hwseq_registers dce121_hwseq_reg = { 772 HWSEQ_VG20_REG_LIST() 773}; 774 775static const struct dce_hwseq_shift dce121_hwseq_shift = { 776 HWSEQ_VG20_MASK_SH_LIST(__SHIFT) 777}; 778 779static const struct dce_hwseq_mask dce121_hwseq_mask = { 780 HWSEQ_VG20_MASK_SH_LIST(_MASK) 781}; 782 783static struct dce_hwseq *dce120_hwseq_create( 784 struct dc_context *ctx) 785{ 786 struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); 787 788 if (hws) { 789 hws->ctx = ctx; 790 hws->regs = &hwseq_reg; 791 hws->shifts = &hwseq_shift; 792 hws->masks = &hwseq_mask; 793 } 794 return hws; 795} 796 797static struct dce_hwseq *dce121_hwseq_create( 798 struct dc_context *ctx) 799{ 800 struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); 801 802 if (hws) { 803 hws->ctx = ctx; 804 hws->regs = &dce121_hwseq_reg; 805 hws->shifts = &dce121_hwseq_shift; 806 hws->masks = &dce121_hwseq_mask; 807 } 808 return hws; 809} 810 811static const struct resource_create_funcs res_create_funcs = { 812 .read_dce_straps = read_dce_straps, 813 .create_audio = create_audio, 814 .create_stream_encoder = dce120_stream_encoder_create, 815 .create_hwseq = dce120_hwseq_create, 816}; 817 818static const struct resource_create_funcs dce121_res_create_funcs = { 819 .read_dce_straps = read_dce_straps, 820 .create_audio = create_audio, 821 .create_stream_encoder = dce120_stream_encoder_create, 822 .create_hwseq = dce121_hwseq_create, 823}; 824 825 826#define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) } 827static const struct dce_mem_input_registers mi_regs[] = { 828 mi_inst_regs(0), 829 mi_inst_regs(1), 830 mi_inst_regs(2), 831 mi_inst_regs(3), 832 mi_inst_regs(4), 833 mi_inst_regs(5), 834}; 835 836static const struct dce_mem_input_shift mi_shifts = { 837 MI_DCE12_MASK_SH_LIST(__SHIFT) 838}; 839 840static const struct dce_mem_input_mask mi_masks = { 841 MI_DCE12_MASK_SH_LIST(_MASK) 842}; 843 844static struct mem_input *dce120_mem_input_create( 845 struct dc_context *ctx, 846 uint32_t inst) 847{ 848 struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), 849 GFP_KERNEL); 850 851 if (!dce_mi) { 852 BREAK_TO_DEBUGGER(); 853 return NULL; 854 } 855 856 dce120_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); 857 return &dce_mi->base; 858} 859 860static struct transform *dce120_transform_create( 861 struct dc_context *ctx, 862 uint32_t inst) 863{ 864 struct dce_transform *transform = 865 kzalloc(sizeof(struct dce_transform), GFP_KERNEL); 866 867 if (!transform) 868 return NULL; 869 870 dce_transform_construct(transform, ctx, inst, 871 &xfm_regs[inst], &xfm_shift, &xfm_mask); 872 transform->lb_memory_size = 0x1404; /*5124*/ 873 return &transform->base; 874} 875 876static void dce120_destroy_resource_pool(struct resource_pool **pool) 877{ 878 struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); 879 880 dce120_resource_destruct(dce110_pool); 881 kfree(dce110_pool); 882 *pool = NULL; 883} 884 885static const struct resource_funcs dce120_res_pool_funcs = { 886 .destroy = dce120_destroy_resource_pool, 887 .link_enc_create = dce120_link_encoder_create, 888 .validate_bandwidth = dce112_validate_bandwidth, 889 .validate_plane = dce100_validate_plane, 890 .add_stream_to_ctx = dce112_add_stream_to_ctx, 891 .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link 892}; 893 894static void bw_calcs_data_update_from_pplib(struct dc *dc) 895{ 896 struct dm_pp_clock_levels_with_latency eng_clks = {0}; 897 struct dm_pp_clock_levels_with_latency mem_clks = {0}; 898 struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; 899 int i; 900 unsigned int clk; 901 unsigned int latency; 902 /*original logic in dal3*/ 903 int memory_type_multiplier = MEMORY_TYPE_MULTIPLIER_CZ; 904 905 /*do system clock*/ 906 if (!dm_pp_get_clock_levels_by_type_with_latency( 907 dc->ctx, 908 DM_PP_CLOCK_TYPE_ENGINE_CLK, 909 &eng_clks) || eng_clks.num_levels == 0) { 910 911 eng_clks.num_levels = 8; 912 clk = 300000; 913 914 for (i = 0; i < eng_clks.num_levels; i++) { 915 eng_clks.data[i].clocks_in_khz = clk; 916 clk += 100000; 917 } 918 } 919 920 /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ 921 dc->bw_vbios->high_sclk = bw_frc_to_fixed( 922 eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); 923 dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( 924 eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); 925 dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( 926 eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); 927 dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( 928 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); 929 dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( 930 eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); 931 dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( 932 eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); 933 dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( 934 eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); 935 dc->bw_vbios->low_sclk = bw_frc_to_fixed( 936 eng_clks.data[0].clocks_in_khz, 1000); 937 938 /*do memory clock*/ 939 if (!dm_pp_get_clock_levels_by_type_with_latency( 940 dc->ctx, 941 DM_PP_CLOCK_TYPE_MEMORY_CLK, 942 &mem_clks) || mem_clks.num_levels == 0) { 943 944 mem_clks.num_levels = 3; 945 clk = 250000; 946 latency = 45; 947 948 for (i = 0; i < eng_clks.num_levels; i++) { 949 mem_clks.data[i].clocks_in_khz = clk; 950 mem_clks.data[i].latency_in_us = latency; 951 clk += 500000; 952 latency -= 5; 953 } 954 955 } 956 957 /* we don't need to call PPLIB for validation clock since they 958 * also give us the highest sclk and highest mclk (UMA clock). 959 * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): 960 * YCLK = UMACLK*m_memoryTypeMultiplier 961 */ 962 if (dc->bw_vbios->memory_type == bw_def_hbm) 963 memory_type_multiplier = MEMORY_TYPE_HBM; 964 965 dc->bw_vbios->low_yclk = bw_frc_to_fixed( 966 mem_clks.data[0].clocks_in_khz * memory_type_multiplier, 1000); 967 dc->bw_vbios->mid_yclk = bw_frc_to_fixed( 968 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * memory_type_multiplier, 969 1000); 970 dc->bw_vbios->high_yclk = bw_frc_to_fixed( 971 mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * memory_type_multiplier, 972 1000); 973 974 /* Now notify PPLib/SMU about which Watermarks sets they should select 975 * depending on DPM state they are in. And update BW MGR GFX Engine and 976 * Memory clock member variables for Watermarks calculations for each 977 * Watermark Set 978 */ 979 clk_ranges.num_wm_sets = 4; 980 clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; 981 clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = 982 eng_clks.data[0].clocks_in_khz; 983 clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = 984 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; 985 clk_ranges.wm_clk_ranges[0].wm_min_mem_clk_in_khz = 986 mem_clks.data[0].clocks_in_khz; 987 clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = 988 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; 989 990 clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; 991 clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = 992 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; 993 /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ 994 clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; 995 clk_ranges.wm_clk_ranges[1].wm_min_mem_clk_in_khz = 996 mem_clks.data[0].clocks_in_khz; 997 clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = 998 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; 999 1000 clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; 1001 clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = 1002 eng_clks.data[0].clocks_in_khz; 1003 clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = 1004 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; 1005 clk_ranges.wm_clk_ranges[2].wm_min_mem_clk_in_khz = 1006 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; 1007 /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ 1008 clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; 1009 1010 clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; 1011 clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = 1012 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; 1013 /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ 1014 clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; 1015 clk_ranges.wm_clk_ranges[3].wm_min_mem_clk_in_khz = 1016 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; 1017 /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ 1018 clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; 1019 1020 /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ 1021 dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); 1022} 1023 1024static uint32_t read_pipe_fuses(struct dc_context *ctx) 1025{ 1026 uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); 1027 /* VG20 support max 6 pipes */ 1028 value = value & 0x3f; 1029 return value; 1030} 1031 1032static bool dce120_resource_construct( 1033 uint8_t num_virtual_links, 1034 struct dc *dc, 1035 struct dce110_resource_pool *pool) 1036{ 1037 unsigned int i; 1038 int j; 1039 struct dc_context *ctx = dc->ctx; 1040 struct irq_service_init_data irq_init_data; 1041 static const struct resource_create_funcs *res_funcs; 1042 bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); 1043 uint32_t pipe_fuses; 1044 1045 ctx->dc_bios->regs = &bios_regs; 1046 1047 pool->base.res_cap = &res_cap; 1048 pool->base.funcs = &dce120_res_pool_funcs; 1049 1050 /* TODO: Fill more data from GreenlandAsicCapability.cpp */ 1051 pool->base.pipe_count = res_cap.num_timing_generator; 1052 pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; 1053 pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; 1054 1055 dc->caps.max_downscale_ratio = 200; 1056 dc->caps.i2c_speed_in_khz = 100; 1057 dc->caps.max_cursor_size = 128; 1058 dc->caps.dual_link_dvi = true; 1059 dc->caps.psp_setup_panel_mode = true; 1060 dc->caps.extended_aux_timeout_support = false; 1061 dc->debug = debug_defaults; 1062 1063 /************************************************* 1064 * Create resources * 1065 *************************************************/ 1066 1067 pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = 1068 dce120_clock_source_create(ctx, ctx->dc_bios, 1069 CLOCK_SOURCE_COMBO_PHY_PLL0, 1070 &clk_src_regs[0], false); 1071 pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = 1072 dce120_clock_source_create(ctx, ctx->dc_bios, 1073 CLOCK_SOURCE_COMBO_PHY_PLL1, 1074 &clk_src_regs[1], false); 1075 pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = 1076 dce120_clock_source_create(ctx, ctx->dc_bios, 1077 CLOCK_SOURCE_COMBO_PHY_PLL2, 1078 &clk_src_regs[2], false); 1079 pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = 1080 dce120_clock_source_create(ctx, ctx->dc_bios, 1081 CLOCK_SOURCE_COMBO_PHY_PLL3, 1082 &clk_src_regs[3], false); 1083 pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = 1084 dce120_clock_source_create(ctx, ctx->dc_bios, 1085 CLOCK_SOURCE_COMBO_PHY_PLL4, 1086 &clk_src_regs[4], false); 1087 pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = 1088 dce120_clock_source_create(ctx, ctx->dc_bios, 1089 CLOCK_SOURCE_COMBO_PHY_PLL5, 1090 &clk_src_regs[5], false); 1091 pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; 1092 1093 pool->base.dp_clock_source = 1094 dce120_clock_source_create(ctx, ctx->dc_bios, 1095 CLOCK_SOURCE_ID_DP_DTO, 1096 &clk_src_regs[0], true); 1097 1098 for (i = 0; i < pool->base.clk_src_count; i++) { 1099 if (pool->base.clock_sources[i] == NULL) { 1100 dm_error("DC: failed to create clock sources!\n"); 1101 BREAK_TO_DEBUGGER(); 1102 goto clk_src_create_fail; 1103 } 1104 } 1105 1106 pool->base.dmcu = dce_dmcu_create(ctx, 1107 &dmcu_regs, 1108 &dmcu_shift, 1109 &dmcu_mask); 1110 if (pool->base.dmcu == NULL) { 1111 dm_error("DC: failed to create dmcu!\n"); 1112 BREAK_TO_DEBUGGER(); 1113 goto res_create_fail; 1114 } 1115 1116 pool->base.abm = dce_abm_create(ctx, 1117 &abm_regs, 1118 &abm_shift, 1119 &abm_mask); 1120 if (pool->base.abm == NULL) { 1121 dm_error("DC: failed to create abm!\n"); 1122 BREAK_TO_DEBUGGER(); 1123 goto res_create_fail; 1124 } 1125 1126 1127 irq_init_data.ctx = dc->ctx; 1128 pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); 1129 if (!pool->base.irqs) 1130 goto irqs_create_fail; 1131 1132 /* VG20: Pipe harvesting enabled, retrieve valid pipe fuses */ 1133 if (is_vg20) 1134 pipe_fuses = read_pipe_fuses(ctx); 1135 1136 /* index to valid pipe resource */ 1137 j = 0; 1138 for (i = 0; i < pool->base.pipe_count; i++) { 1139 if (is_vg20) { 1140 if ((pipe_fuses & (1 << i)) != 0) { 1141 dm_error("DC: skip invalid pipe %d!\n", i); 1142 continue; 1143 } 1144 } 1145 1146 pool->base.timing_generators[j] = 1147 dce120_timing_generator_create( 1148 ctx, 1149 i, 1150 &dce120_tg_offsets[i]); 1151 if (pool->base.timing_generators[j] == NULL) { 1152 BREAK_TO_DEBUGGER(); 1153 dm_error("DC: failed to create tg!\n"); 1154 goto controller_create_fail; 1155 } 1156 1157 pool->base.mis[j] = dce120_mem_input_create(ctx, i); 1158 1159 if (pool->base.mis[j] == NULL) { 1160 BREAK_TO_DEBUGGER(); 1161 dm_error( 1162 "DC: failed to create memory input!\n"); 1163 goto controller_create_fail; 1164 } 1165 1166 pool->base.ipps[j] = dce120_ipp_create(ctx, i); 1167 if (pool->base.ipps[i] == NULL) { 1168 BREAK_TO_DEBUGGER(); 1169 dm_error( 1170 "DC: failed to create input pixel processor!\n"); 1171 goto controller_create_fail; 1172 } 1173 1174 pool->base.transforms[j] = dce120_transform_create(ctx, i); 1175 if (pool->base.transforms[i] == NULL) { 1176 BREAK_TO_DEBUGGER(); 1177 dm_error( 1178 "DC: failed to create transform!\n"); 1179 goto res_create_fail; 1180 } 1181 1182 pool->base.opps[j] = dce120_opp_create( 1183 ctx, 1184 i); 1185 if (pool->base.opps[j] == NULL) { 1186 BREAK_TO_DEBUGGER(); 1187 dm_error( 1188 "DC: failed to create output pixel processor!\n"); 1189 } 1190 1191 /* check next valid pipe */ 1192 j++; 1193 } 1194 1195 for (i = 0; i < pool->base.res_cap->num_ddc; i++) { 1196 pool->base.engines[i] = dce120_aux_engine_create(ctx, i); 1197 if (pool->base.engines[i] == NULL) { 1198 BREAK_TO_DEBUGGER(); 1199 dm_error( 1200 "DC:failed to create aux engine!!\n"); 1201 goto res_create_fail; 1202 } 1203 pool->base.hw_i2cs[i] = dce120_i2c_hw_create(ctx, i); 1204 if (pool->base.hw_i2cs[i] == NULL) { 1205 BREAK_TO_DEBUGGER(); 1206 dm_error( 1207 "DC:failed to create i2c engine!!\n"); 1208 goto res_create_fail; 1209 } 1210 pool->base.sw_i2cs[i] = NULL; 1211 } 1212 1213 /* valid pipe num */ 1214 pool->base.pipe_count = j; 1215 pool->base.timing_generator_count = j; 1216 1217 if (is_vg20) 1218 res_funcs = &dce121_res_create_funcs; 1219 else 1220 res_funcs = &res_create_funcs; 1221 1222 if (!resource_construct(num_virtual_links, dc, &pool->base, res_funcs)) 1223 goto res_create_fail; 1224 1225 /* Create hardware sequencer */ 1226 if (!dce120_hw_sequencer_create(dc)) 1227 goto controller_create_fail; 1228 1229 dc->caps.max_planes = pool->base.pipe_count; 1230 1231 for (i = 0; i < dc->caps.max_planes; ++i) 1232 dc->caps.planes[i] = plane_cap; 1233 1234 bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); 1235 1236 bw_calcs_data_update_from_pplib(dc); 1237 1238 return true; 1239 1240irqs_create_fail: 1241controller_create_fail: 1242clk_src_create_fail: 1243res_create_fail: 1244 1245 dce120_resource_destruct(pool); 1246 1247 return false; 1248} 1249 1250struct resource_pool *dce120_create_resource_pool( 1251 uint8_t num_virtual_links, 1252 struct dc *dc) 1253{ 1254 struct dce110_resource_pool *pool = 1255 kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); 1256 1257 if (!pool) 1258 return NULL; 1259 1260 if (dce120_resource_construct(num_virtual_links, dc, pool)) 1261 return &pool->base; 1262 1263 kfree(pool); 1264 BREAK_TO_DEBUGGER(); 1265 return NULL; 1266} 1267