Commit 7992a629 authored by Alex Deucher's avatar Alex Deucher Committed by Alex Deucher

drm/amd/disply/dc: add resource support for DCE8 APUs (v2)

Add the appropriate resources for APUs:
KV:    4 pipes, 7 dig, 3 PPLLs
KB/ML: 2 pipes, 6 dig, 2 PPLLs

v2: rebase changes
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ebfdf0d0
......@@ -101,9 +101,15 @@ struct resource_pool *dc_create_resource_pool(
switch (dc_version) {
case DCE_VERSION_8_0:
res_pool = dce80_create_resource_pool(
num_virtual_links, dc);
break;
case DCE_VERSION_8_1:
res_pool = dce81_create_resource_pool(
num_virtual_links, dc);
break;
case DCE_VERSION_8_3:
res_pool = dce80_create_resource_pool(
res_pool = dce83_create_resource_pool(
num_virtual_links, dc);
break;
case DCE_VERSION_10_0:
......
......@@ -350,6 +350,20 @@ static const struct resource_caps res_cap = {
.num_pll = 3,
};
static const struct resource_caps res_cap_81 = {
.num_timing_generator = 4,
.num_audio = 7,
.num_stream_encoder = 7,
.num_pll = 3,
};
static const struct resource_caps res_cap_83 = {
.num_timing_generator = 2,
.num_audio = 6,
.num_stream_encoder = 6,
.num_pll = 2,
};
#define CTX ctx
#define REG(reg) mm ## reg
......@@ -829,7 +843,7 @@ static const struct resource_funcs dce80_res_pool_funcs = {
.validate_plane = dce100_validate_plane
};
static bool construct(
static bool dce80_construct(
uint8_t num_virtual_links,
struct core_dc *dc,
struct dce110_resource_pool *pool)
......@@ -987,10 +1001,335 @@ struct resource_pool *dce80_create_resource_pool(
if (!pool)
return NULL;
if (construct(num_virtual_links, dc, pool))
if (dce80_construct(num_virtual_links, dc, pool))
return &pool->base;
BREAK_TO_DEBUGGER();
return NULL;
}
static bool dce81_construct(
uint8_t num_virtual_links,
struct core_dc *dc,
struct dce110_resource_pool *pool)
{
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 = &res_cap_81;
pool->base.funcs = &dce80_res_pool_funcs;
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap_81.num_timing_generator;
dc->public.caps.max_downscale_ratio = 200;
dc->public.caps.i2c_speed_in_khz = 40;
dc->public.caps.max_cursor_size = 128;
/*************************************************
* 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 =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
pool->base.clock_sources[0] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false);
pool->base.clock_sources[1] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
pool->base.clock_sources[2] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
pool->base.clk_src_count = 3;
} else {
pool->base.dp_clock_source =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true);
pool->base.clock_sources[0] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false);
pool->base.clock_sources[1] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false);
pool->base.clk_src_count = 2;
}
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 = dce_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;
}
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_dce80_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] = dce80_timing_generator_create(
ctx, i, &dce80_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] = dce80_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] = dce80_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] = dce80_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] = dce80_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;
}
}
dc->public.caps.max_planes = pool->base.pipe_count;
if (!resource_construct(num_virtual_links, dc, &pool->base,
&res_create_funcs))
goto res_create_fail;
/* Create hardware sequencer */
if (!dce80_hw_sequencer_construct(dc))
goto res_create_fail;
return true;
res_create_fail:
destruct(pool);
return false;
}
struct resource_pool *dce81_create_resource_pool(
uint8_t num_virtual_links,
struct core_dc *dc)
{
struct dce110_resource_pool *pool =
dm_alloc(sizeof(struct dce110_resource_pool));
if (!pool)
return NULL;
if (dce81_construct(num_virtual_links, dc, pool))
return &pool->base;
BREAK_TO_DEBUGGER();
return NULL;
}
static bool dce83_construct(
uint8_t num_virtual_links,
struct core_dc *dc,
struct dce110_resource_pool *pool)
{
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 = &res_cap_83;
pool->base.funcs = &dce80_res_pool_funcs;
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap_83.num_timing_generator;
dc->public.caps.max_downscale_ratio = 200;
dc->public.caps.i2c_speed_in_khz = 40;
dc->public.caps.max_cursor_size = 128;
/*************************************************
* 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 =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true);
pool->base.clock_sources[0] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false);
pool->base.clock_sources[1] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false);
pool->base.clk_src_count = 2;
} else {
pool->base.dp_clock_source =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true);
pool->base.clock_sources[0] =
dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false);
pool->base.clk_src_count = 1;
}
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 = dce_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;
}
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_dce80_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] = dce80_timing_generator_create(
ctx, i, &dce80_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] = dce80_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] = dce80_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] = dce80_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] = dce80_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;
}
}
dc->public.caps.max_planes = pool->base.pipe_count;
if (!resource_construct(num_virtual_links, dc, &pool->base,
&res_create_funcs))
goto res_create_fail;
/* Create hardware sequencer */
if (!dce80_hw_sequencer_construct(dc))
goto res_create_fail;
return true;
res_create_fail:
destruct(pool);
return false;
}
struct resource_pool *dce83_create_resource_pool(
uint8_t num_virtual_links,
struct core_dc *dc)
{
struct dce110_resource_pool *pool =
dm_alloc(sizeof(struct dce110_resource_pool));
if (!pool)
return NULL;
if (dce83_construct(num_virtual_links, dc, pool))
return &pool->base;
BREAK_TO_DEBUGGER();
return NULL;
}
......@@ -35,5 +35,13 @@ struct resource_pool *dce80_create_resource_pool(
uint8_t num_virtual_links,
struct core_dc *dc);
struct resource_pool *dce81_create_resource_pool(
uint8_t num_virtual_links,
struct core_dc *dc);
struct resource_pool *dce83_create_resource_pool(
uint8_t num_virtual_links,
struct core_dc *dc);
#endif /* __DC_RESOURCE_DCE80_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment