static bool construct( uint8_t num_virtual_links, struct dc *dc, struct dce110_resource_pool *pool, struct hw_asic_id asic_id) { unsigned int i; struct dc_context *ctx = dc->ctx; struct dc_firmware_info info; struct dc_bios *bp; struct dm_pp_static_clock_info static_clk_info = {0}; ctx->dc_bios->regs = &bios_regs; pool->base.res_cap = dce110_resource_cap(&ctx->asic_id); pool->base.funcs = &dce110_res_pool_funcs; /************************************************* * Resource + asic cap harcoding * *************************************************/ pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.underlay_pipe_index = pool->base.pipe_count; pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 150; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 128; dc->caps.is_apu = true; /************************************************* * Create resources * *************************************************/ bp = ctx->dc_bios; if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && info.external_clock_source_frequency_for_dp != 0) { pool->base.dp_clock_source = dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); pool->base.clock_sources[0] = dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); pool->base.clock_sources[1] = dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); pool->base.clk_src_count = 2; /* TODO: find out if CZ support 3 PLLs */ } if (pool->base.dp_clock_source == NULL) { dm_error("DC: failed to create dp clock source!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } for (i = 0; i < pool->base.clk_src_count; i++) { if (pool->base.clock_sources[i] == NULL) { dm_error("DC: failed to create clock sources!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } } pool->base.display_clock = dce110_disp_clk_create(ctx, &disp_clk_regs, &disp_clk_shift, &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } pool->base.dmcu = dce_dmcu_create(ctx, &dmcu_regs, &dmcu_shift, &dmcu_mask); if (pool->base.dmcu == NULL) { dm_error("DC: failed to create dmcu!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } pool->base.abm = dce_abm_create(ctx, &abm_regs, &abm_shift, &abm_mask); if (pool->base.abm == NULL) { dm_error("DC: failed to create abm!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } /* get static clock information for PPLIB or firmware, save * max_clock_state */ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; pool->base.irqs = dal_irq_service_dce110_create(&init_data); if (!pool->base.irqs) goto res_create_fail; } for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = dce110_timing_generator_create( ctx, i, &dce110_tg_offsets[i]); if (pool->base.timing_generators[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); goto res_create_fail; } pool->base.mis[i] = dce110_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); goto res_create_fail; } pool->base.ipps[i] = dce110_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create input pixel processor!\n"); goto res_create_fail; } pool->base.transforms[i] = dce110_transform_create(ctx, i); if (pool->base.transforms[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create transform!\n"); goto res_create_fail; } pool->base.opps[i] = dce110_opp_create(ctx, i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create output pixel processor!\n"); goto res_create_fail; } } #if defined(CONFIG_DRM_AMD_DC_FBC) dc->fbc_compressor = dce110_compressor_create(ctx); #endif if (!underlay_create(ctx, &pool->base)) goto res_create_fail; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) goto res_create_fail; /* Create hardware sequencer */ dce110_hw_sequencer_construct(dc); dc->caps.max_planes = pool->base.pipe_count; bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); return true; res_create_fail: destruct(pool); return false; }
static bool construct( uint8_t num_virtual_links, struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; struct dc_context *ctx = dc->ctx; struct irq_service_init_data irq_init_data; ctx->dc_bios->regs = &bios_regs; pool->base.res_cap = &res_cap; pool->base.funcs = &dce120_res_pool_funcs; /* TODO: Fill more data from GreenlandAsicCapability.cpp */ pool->base.pipe_count = res_cap.num_timing_generator; pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 128; dc->caps.dual_link_dvi = true; dc->debug = debug_defaults; /************************************************* * Create resources * *************************************************/ pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL0, &clk_src_regs[0], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL1, &clk_src_regs[1], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL2, &clk_src_regs[2], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL3, &clk_src_regs[3], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL4, &clk_src_regs[4], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL5, &clk_src_regs[5], false); pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; pool->base.dp_clock_source = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true); for (i = 0; i < pool->base.clk_src_count; i++) { if (pool->base.clock_sources[i] == NULL) { dm_error("DC: failed to create clock sources!\n"); BREAK_TO_DEBUGGER(); goto clk_src_create_fail; } } pool->base.display_clock = dce120_disp_clk_create(ctx); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); goto disp_clk_create_fail; } pool->base.dmcu = dce_dmcu_create(ctx, &dmcu_regs, &dmcu_shift, &dmcu_mask); if (pool->base.dmcu == NULL) { dm_error("DC: failed to create dmcu!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } pool->base.abm = dce_abm_create(ctx, &abm_regs, &abm_shift, &abm_mask); if (pool->base.abm == NULL) { dm_error("DC: failed to create abm!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } irq_init_data.ctx = dc->ctx; pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); if (!pool->base.irqs) goto irqs_create_fail; for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = dce120_timing_generator_create( ctx, i, &dce120_tg_offsets[i]); if (pool->base.timing_generators[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); goto controller_create_fail; } pool->base.mis[i] = dce120_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); goto controller_create_fail; } pool->base.ipps[i] = dce120_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create input pixel processor!\n"); goto controller_create_fail; } pool->base.transforms[i] = dce120_transform_create(ctx, i); if (pool->base.transforms[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create transform!\n"); goto res_create_fail; } pool->base.opps[i] = dce120_opp_create( ctx, i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create output pixel processor!\n"); } } if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) goto res_create_fail; /* Create hardware sequencer */ if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; dc->caps.max_planes = pool->base.pipe_count; bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); return true; irqs_create_fail: controller_create_fail: disp_clk_create_fail: clk_src_create_fail: res_create_fail: destruct(pool); return false; }
static bool construct( uint8_t num_virtual_links, struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; int j; struct dc_context *ctx = dc->ctx; struct irq_service_init_data irq_init_data; bool harvest_enabled = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); uint32_t pipe_fuses; ctx->dc_bios->regs = &bios_regs; pool->base.res_cap = &res_cap; pool->base.funcs = &dce120_res_pool_funcs; /* TODO: Fill more data from GreenlandAsicCapability.cpp */ pool->base.pipe_count = res_cap.num_timing_generator; pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 128; dc->caps.dual_link_dvi = true; dc->caps.psp_setup_panel_mode = true; dc->debug = debug_defaults; /************************************************* * Create resources * *************************************************/ pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL0, &clk_src_regs[0], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL1, &clk_src_regs[1], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL2, &clk_src_regs[2], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL3, &clk_src_regs[3], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL4, &clk_src_regs[4], false); pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_COMBO_PHY_PLL5, &clk_src_regs[5], false); pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; pool->base.dp_clock_source = dce120_clock_source_create(ctx, ctx->dc_bios, CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true); for (i = 0; i < pool->base.clk_src_count; i++) { if (pool->base.clock_sources[i] == NULL) { dm_error("DC: failed to create clock sources!\n"); BREAK_TO_DEBUGGER(); goto clk_src_create_fail; } } pool->base.dccg = dce120_dccg_create(ctx); if (pool->base.dccg == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); goto dccg_create_fail; } pool->base.dmcu = dce_dmcu_create(ctx, &dmcu_regs, &dmcu_shift, &dmcu_mask); if (pool->base.dmcu == NULL) { dm_error("DC: failed to create dmcu!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } pool->base.abm = dce_abm_create(ctx, &abm_regs, &abm_shift, &abm_mask); if (pool->base.abm == NULL) { dm_error("DC: failed to create abm!\n"); BREAK_TO_DEBUGGER(); goto res_create_fail; } irq_init_data.ctx = dc->ctx; pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); if (!pool->base.irqs) goto irqs_create_fail; /* retrieve valid pipe fuses */ if (harvest_enabled) pipe_fuses = read_pipe_fuses(ctx); /* index to valid pipe resource */ j = 0; for (i = 0; i < pool->base.pipe_count; i++) { if (harvest_enabled) { if ((pipe_fuses & (1 << i)) != 0) { dm_error("DC: skip invalid pipe %d!\n", i); continue; } } pool->base.timing_generators[j] = dce120_timing_generator_create( ctx, i, &dce120_tg_offsets[i]); if (pool->base.timing_generators[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); goto controller_create_fail; } pool->base.mis[j] = dce120_mem_input_create(ctx, i); if (pool->base.mis[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); goto controller_create_fail; } pool->base.ipps[j] = dce120_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create input pixel processor!\n"); goto controller_create_fail; } pool->base.transforms[j] = dce120_transform_create(ctx, i); if (pool->base.transforms[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create transform!\n"); goto res_create_fail; } pool->base.opps[j] = dce120_opp_create( ctx, i); if (pool->base.opps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create output pixel processor!\n"); } /* check next valid pipe */ j++; } for (i = 0; i < pool->base.res_cap->num_ddc; i++) { pool->base.engines[i] = dce120_aux_engine_create(ctx, i); if (pool->base.engines[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC:failed to create aux engine!!\n"); goto res_create_fail; } pool->base.hw_i2cs[i] = dce120_i2c_hw_create(ctx, i); if (pool->base.hw_i2cs[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC:failed to create i2c engine!!\n"); goto res_create_fail; } pool->base.sw_i2cs[i] = NULL; } /* valid pipe num */ pool->base.pipe_count = j; pool->base.timing_generator_count = j; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) goto res_create_fail; /* Create hardware sequencer */ if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; dc->caps.max_planes = pool->base.pipe_count; bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); return true; irqs_create_fail: controller_create_fail: dccg_create_fail: clk_src_create_fail: res_create_fail: destruct(pool); return false; }