* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-03-06 13:47 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-03-06 13:47 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Kernel Mailing List, Linux Next Mailing List, Matt Roper,
Rodrigo Vivi
[-- Attachment #1: Type: text/plain, Size: 880 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/xe/xe_wa.c
between commit:
89865e6dc8487 ("drm/xe/xe2_hpg: Correct implementation of Wa_16025250150")
from the drm-fixes tree and commit:
941f538b0af81 ("drm/xe: Consolidate workaround entries for Wa_16021867713")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/xe/xe_wa.c
index 462c2fa712e01,289acac2c3c82..0000000000000
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-07-17 14:41 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-07-17 14:41 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Ce Sun, Linux Kernel Mailing List,
Linux Next Mailing List, Mario Limonciello, Tvrtko Ursulin,
Yang Wang
[-- Attachment #1: Type: text/plain, Size: 4214 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
between commit:
6e4bc34568e38 ("drm/amd: Create a device link between APU display and XHCI devices")
from the drm-fixes tree and commits:
07c93d7eeb0d9 ("drm/amd: Create a device link between APU display and XHCI devices")
958430a1f068f ("drm/amd/pm: retire legacy smu ras driver framework")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index e3a89e9a9df41,7ea7c4a5279be..0000000000000
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@@ -852,8 -852,6 +852,6 @@@ struct pptable_funcs
*/
int (*set_default_dpm_table)(struct smu_context *smu);
- int (*set_power_state)(struct smu_context *smu);
-
/**
* @populate_umd_state_clk: Populate the UMD power state table with
* defaults.
@@@ -906,16 -904,6 +904,6 @@@
struct
pp_clock_levels_with_latency
*clocks);
- /**
- * @get_clock_by_type_with_voltage: Get the speed and voltage of a clock
- * domain.
- */
- int (*get_clock_by_type_with_voltage)(struct smu_context *smu,
- enum amd_pp_clock_type type,
- struct
- pp_clock_levels_with_voltage
- *clocks);
-
/**
* @get_power_profile_mode: Print all power profile modes to
* buffer. Star current mode.
@@@ -1357,11 -1345,6 +1345,6 @@@
*/
int (*register_irq_handler)(struct smu_context *smu);
- /**
- * @set_azalia_d3_pme: Wake the audio decode engine from d3 sleep.
- */
- int (*set_azalia_d3_pme)(struct smu_context *smu);
-
/**
* @get_max_sustainable_clocks_by_dc: Get a copy of the max sustainable
* clock speeds table.
@@@ -1378,18 -1361,6 +1361,6 @@@
*/
int (*get_bamaco_support)(struct smu_context *smu);
- /**
- * @baco_get_state: Get the current BACO state.
- *
- * Return: Current BACO state.
- */
- enum smu_baco_state (*baco_get_state)(struct smu_context *smu);
-
- /**
- * @baco_set_state: Enter/exit BACO.
- */
- int (*baco_set_state)(struct smu_context *smu, enum smu_baco_state state);
-
/**
* @baco_enter: Enter BACO.
*/
@@@ -1651,12 -1622,6 +1622,6 @@@
int (*ras_send_msg)(struct smu_context *smu,
enum smu_message_type msg, uint32_t param, uint32_t *read_arg);
- /**
- * @get_ras_smu_drv: Get RAS smu driver interface
- * Return: ras_smu_drv *
- */
- int (*get_ras_smu_drv)(struct smu_context *smu, const struct ras_smu_drv **ras_smu_drv);
-
/**
* @set_power_dep: Create or destroy a power dependency link
* from an integrated xHCI controller to the GPU so that the GPU is
@@@ -1962,7 -1927,13 +1927,13 @@@ int smu_link_reset(struct smu_context *
extern const struct amd_ip_funcs smu_ip_funcs;
- bool is_support_sw_smu(struct amdgpu_device *adev);
+ void amdgpu_smu_early_init(struct amdgpu_device *adev);
+
+ static inline bool is_support_sw_smu(struct amdgpu_device *adev)
+ {
+ return adev->is_sw_smu;
+ }
+
bool is_support_cclk_dpm(struct amdgpu_device *adev);
int smu_write_watermarks_table(struct smu_context *smu);
@@@ -2005,7 -1976,6 +1976,6 @@@ int smu_set_pm_policy(struct smu_contex
int level);
ssize_t smu_get_pm_policy_info(struct smu_context *smu,
enum pp_pm_policy p_type, char *sysbuf);
- const struct ras_smu_drv *smu_get_ras_smu_driver(void *handle);
int amdgpu_smu_ras_send_msg(struct amdgpu_device *adev, enum smu_message_type msg,
uint32_t param, uint32_t *readarg);
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-07-17 14:40 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-07-17 14:40 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Arnd Bergmann, Bhuvanachandra Pinninti,
Charlene Liu, Chenyu Chen, George Zhang, Honglei Huang,
James Lin, Leo Li, Linux Kernel Mailing List,
Linux Next Mailing List, Rafal Ostrowski, Tom Chung
[-- Attachment #1: Type: text/plain, Size: 38293 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/dc/core/dc.c
between commit:
d73f4e118dc4c ("drm/amd/display: check GRPH_FLIP status before sending event")
from the drm-fixes tree and commits:
f64a9be565368 ("drm/amd/display: check GRPH_FLIP status before sending event")
72b94048020ce ("drm/amd/display: limit reuse dsc capable bootup timing")
98e08a815ef60 ("drm/amd/display: Tear down dangling pipe on boot to fix s0i3")
2a5810782369b ("drm/amd/display: program dither on all OPP heads under ODM combine")
f3403ab74a29f ("drm/amd/display: Add block sequence support for bandwidth programming operations")
991e0516a8072 ("drm/amd/display: use kvzalloc to allocate struct dc")
9e0896fa6f7db ("drm/amd/display: avoid large stack allocation in commit_planes_do_stream_update_sequence")
c1199393ec559 ("drm/amd/display: Refactor surface_update_flags to flat struct with helpers")
b008c67efb36b ("drm/amd/display: Introduce dc_plane_cm and migrate surface update color path")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/display/dc/core/dc.c
index e25b94b65daca,8d77158229f1b..0000000000000
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@@ -769,22 -769,23 +769,23 @@@ void dc_stream_set_dither_option(struc
{
struct bit_depth_reduction_params params;
struct dc_link *link = stream->link;
- struct pipe_ctx *pipes = NULL;
+ struct resource_context *res_ctx = &link->dc->current_state->res_ctx;
+ struct pipe_ctx *otg_master;
+ struct pipe_ctx *opp_heads[MAX_PIPES];
+ int opp_cnt;
int i;
- for (i = 0; i < MAX_PIPES; i++) {
- if (link->dc->current_state->res_ctx.pipe_ctx[i].stream ==
- stream) {
- pipes = &link->dc->current_state->res_ctx.pipe_ctx[i];
- break;
- }
- }
-
- if (!pipes)
+ otg_master = resource_get_otg_master_for_stream(res_ctx, stream);
+ if (!otg_master)
return;
if (option > DITHER_OPTION_MAX)
return;
+ opp_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads);
+
+ if (opp_cnt == 0)
+ return;
+
dc_exit_ips_for_hw_access(stream->ctx->dc);
stream->dither_option = option;
@@@ -793,16 -794,30 +794,30 @@@
resource_build_bit_depth_reduction_params(stream, ¶ms);
stream->bit_depth_params = params;
- if (pipes->plane_res.xfm &&
- pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth) {
- pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
- pipes->plane_res.xfm,
- pipes->plane_res.scl_data.lb_params.depth,
- &stream->bit_depth_params);
- }
+ /*
+ * Program bit-depth reduction (dither) on every OPP head of the
+ * stream. Under ODM combine there is more than one OPP head and they
+ * must all be kept in sync, otherwise (e.g. when CRC capture requests
+ * dither off) a secondary ODM segment can keep dither enabled and
+ * produce a different CRC than the primary segment.
+ */
+ for (i = 0; i < opp_cnt; i++) {
+ struct pipe_ctx *opp_head = opp_heads[i];
- pipes->stream_res.opp->funcs->
- opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms);
+ if (opp_head->plane_res.xfm &&
+ opp_head->plane_res.xfm->funcs->transform_set_pixel_storage_depth) {
+ opp_head->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
+ opp_head->plane_res.xfm,
+ opp_head->plane_res.scl_data.lb_params.depth,
+ &stream->bit_depth_params);
+ }
+
+ if (opp_head->stream_res.opp &&
+ opp_head->stream_res.opp->funcs->opp_program_bit_depth_reduction) {
+ opp_head->stream_res.opp->funcs->opp_program_bit_depth_reduction(
+ opp_head->stream_res.opp, ¶ms);
+ }
+ }
}
bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream)
@@@ -1930,6 -1945,13 +1945,13 @@@ bool dc_validate_boot_timing(const stru
struct display_stream_compressor *dsc = NULL;
struct dcn_dsc_state dsc_state = {0};
+ if (dc->ctx->dce_version < DCN_VERSION_4_2) {
+ /*vbios enabled eDP dsc for one of DCN315 only but it has known issue,
+ since there is no production bios update, block it there*/
+ DC_LOG_DEBUG("boot timing validation failed due to unsupported DSC on this ASIC\n");
+ return false;
+ }
+
/* Find DSC associated with this timing generator */
if (tg_inst < (unsigned int)dc->res_pool->res_cap->num_dsc) {
dsc = dc->res_pool->dscs[tg_inst];
@@@ -2310,7 -2332,7 +2332,7 @@@ static enum dc_status dc_commit_state_n
for (i = 0; i < context->stream_count; i++) {
uint32_t prev_dsc_changed = context->streams[i]->update_flags.bits.dsc_changed;
- context->streams[i]->update_flags.raw = 0xFFFFFFFF;
+ stream_update_flags_set_full(&context->streams[i]->update_flags);
context->streams[i]->update_flags.bits.dsc_changed = prev_dsc_changed;
}
@@@ -2416,7 -2438,7 +2438,7 @@@
/* Clear update flags that were set earlier to avoid redundant programming */
for (i = 0; i < context->stream_count; i++) {
- context->streams[i]->update_flags.raw = 0x0;
+ stream_update_flags_clear(&context->streams[i]->update_flags);
}
old_state = dc->current_state;
@@@ -2764,7 -2786,7 +2786,7 @@@ static bool is_surface_in_context
static struct surface_update_descriptor get_plane_info_update_type(const struct dc_surface_update *u)
{
- union surface_update_flags *update_flags = &u->surface->update_flags;
+ struct pipe_update_bits *update_bits = &u->surface->update_bits;
struct surface_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
if (!u->plane_info)
@@@ -2774,37 -2796,37 +2796,37 @@@
elevate_update_type(&update_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
if (u->plane_info->color_space != u->surface->color_space) {
- update_flags->bits.color_space_change = 1;
+ update_bits->color_space_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
}
if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) {
- update_flags->bits.horizontal_mirror_change = 1;
+ update_bits->horizontal_mirror_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
}
if (u->plane_info->rotation != u->surface->rotation) {
- update_flags->bits.rotation_change = 1;
+ update_bits->rotation_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
if (u->plane_info->format != u->surface->format) {
- update_flags->bits.pixel_format_change = 1;
+ update_bits->pixel_format_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
if (u->plane_info->stereo_format != u->surface->stereo_format) {
- update_flags->bits.stereo_format_change = 1;
+ update_bits->stereo_format_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) {
- update_flags->bits.per_pixel_alpha_change = 1;
+ update_bits->per_pixel_alpha_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
}
if (u->plane_info->global_alpha_value != u->surface->global_alpha_value) {
- update_flags->bits.global_alpha_change = 1;
+ update_bits->global_alpha_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
}
@@@ -2816,7 -2838,7 +2838,7 @@@
* stutter period calculation. Triggering a full update will
* recalculate stutter period.
*/
- update_flags->bits.dcc_change = 1;
+ update_bits->dcc_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
@@@ -2825,25 -2847,25 +2847,25 @@@
/* different bytes per element will require full bandwidth
* and DML calculation
*/
- update_flags->bits.bpp_change = 1;
+ update_bits->bpp_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
if (u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch
|| u->plane_info->plane_size.chroma_pitch != u->surface->plane_size.chroma_pitch) {
- update_flags->bits.plane_size_change = 1;
+ update_bits->plane_size_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
}
const struct dc_tiling_info *tiling = &u->plane_info->tiling_info;
if (memcmp(tiling, &u->surface->tiling_info, sizeof(*tiling)) != 0) {
- update_flags->bits.swizzle_change = 1;
+ update_bits->swizzle_change = 1;
if (tiling->flags.avoid_full_update_on_tiling_change) {
elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
} else {
- update_flags->bits.bandwidth_change = 1;
+ update_bits->bandwidth_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
}
@@@ -2853,10 -2875,10 +2875,10 @@@
}
static struct surface_update_descriptor get_scaling_info_update_type(
- const struct dc_check_config *check_config,
- const struct dc_surface_update *u)
+ const struct dc_check_config *check_config,
+ const struct dc_surface_update *u)
{
- union surface_update_flags *update_flags = &u->surface->update_flags;
+ struct pipe_update_bits *update_bits = &u->surface->update_bits;
struct surface_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
if (!u->scaling_info)
@@@ -2873,26 -2895,26 +2895,26 @@@
|| u->scaling_info->clip_rect.height != u->surface->clip_rect.height
|| u->scaling_info->scaling_quality.integer_scaling !=
u->surface->scaling_quality.integer_scaling) {
- update_flags->bits.scaling_change = 1;
+ update_bits->scaling_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
if (u->scaling_info->src_rect.width > u->surface->src_rect.width
|| u->scaling_info->src_rect.height > u->surface->src_rect.height)
/* Making src rect bigger requires a bandwidth change */
- update_flags->bits.clock_change = 1;
+ update_bits->clock_change = 1;
if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width
|| u->scaling_info->dst_rect.height < u->surface->dst_rect.height)
&& (u->scaling_info->dst_rect.width < u->surface->src_rect.width
|| u->scaling_info->dst_rect.height < u->surface->src_rect.height))
/* Making dst rect smaller requires a bandwidth change */
- update_flags->bits.bandwidth_change = 1;
+ update_bits->bandwidth_change = 1;
if (u->scaling_info->src_rect.width > (int)check_config->max_optimizable_video_width &&
(u->scaling_info->clip_rect.width > u->surface->clip_rect.width ||
u->scaling_info->clip_rect.height > u->surface->clip_rect.height))
/* Changing clip size of a large surface may result in MPC slice count change */
- update_flags->bits.bandwidth_change = 1;
+ update_bits->bandwidth_change = 1;
}
if (u->scaling_info->src_rect.x != u->surface->src_rect.x
@@@ -2902,7 -2924,7 +2924,7 @@@
|| u->scaling_info->dst_rect.x != u->surface->dst_rect.x
|| u->scaling_info->dst_rect.y != u->surface->dst_rect.y) {
elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
- update_flags->bits.position_change = 1;
+ update_bits->position_change = 1;
}
return update_type;
@@@ -2913,15 -2935,15 +2935,15 @@@ static struct surface_update_descripto
struct dc_surface_update *u)
{
struct surface_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
- union surface_update_flags *update_flags = &u->surface->update_flags;
+ struct pipe_update_bits *update_bits = &u->surface->update_bits;
if (u->surface->force_full_update) {
- update_flags->raw = 0xFFFFFFFF;
+ dc_pipe_update_bits_set_full(update_bits);
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
return overall_type;
}
- update_flags->raw = 0; // Reset all flags
+ dc_pipe_update_bits_clear(update_bits);
struct surface_update_descriptor inner_type = get_plane_info_update_type(u);
@@@ -2931,87 -2953,112 +2953,112 @@@
elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor);
if (u->flip_addr) {
- update_flags->bits.addr_update = 1;
+ update_bits->addr_update = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
if (u->flip_addr->address.tmz_surface != u->surface->address.tmz_surface) {
- update_flags->bits.tmz_changed = 1;
+ update_bits->tmz_changed = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
}
if (u->in_transfer_func) {
- update_flags->bits.in_transfer_func_change = 1;
+ update_bits->in_transfer_func_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
}
if (u->input_csc_color_matrix) {
- update_flags->bits.input_csc_change = 1;
+ update_bits->input_csc_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
if (u->cursor_csc_color_matrix) {
- update_flags->bits.cursor_csc_color_matrix_change = 1;
+ update_bits->cursor_csc_color_matrix_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
if (u->coeff_reduction_factor) {
- update_flags->bits.coeff_reduction_change = 1;
+ update_bits->coeff_reduction_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
if (u->gamut_remap_matrix) {
- update_flags->bits.gamut_remap_change = 1;
+ update_bits->gamut_remap_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
- if (u->blend_tf || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
- update_flags->bits.gamma_change = 1;
+ if ((u->cm && u->cm->flags.bits.blend_enable) ||
+ (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
+ update_bits->gamma_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
- if (u->lut3d_func || u->func_shaper) {
- update_flags->bits.lut_3d = 1;
+ if (u->cm && (u->cm->flags.bits.lut3d_enable || u->cm->flags.bits.shaper_enable)) {
+ update_bits->lut_3d = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
+ if (u->cm && u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable &&
+ u->cm->flags.bits.lut3d_enable && u->surface->cm.flags.bits.lut3d_enable) {
+ /* Toggling 3DLUT loading between DMA and Host is illegal */
+ BREAK_TO_DEBUGGER();
+ }
+
+ if (u->cm && u->cm->flags.bits.lut3d_enable && !u->cm->flags.bits.lut3d_dma_enable) {
+ /* Host loading 3DLUT requires full update but only stream lock */
+ elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_STREAM);
+ }
+
if (u->hdr_mult.value)
if (u->hdr_mult.value != u->surface->hdr_mult.value) {
// TODO: Should be fast?
- update_flags->bits.hdr_mult = 1;
+ update_bits->hdr_mult = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
}
if (u->sdr_white_level_nits)
if (u->sdr_white_level_nits != u->surface->sdr_white_level_nits) {
// TODO: Should be fast?
- update_flags->bits.sdr_white_level_nits = 1;
+ update_bits->sdr_white_level_nits = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
if (u->cm_hist_control) {
- update_flags->bits.cm_hist_change = 1;
+ update_bits->cm_hist_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
- if (u->cm2_params) {
- if (u->cm2_params->component_settings.shaper_3dlut_setting != u->surface->mcm_shaper_3dlut_setting
- || u->cm2_params->component_settings.lut1d_enable != u->surface->mcm_lut1d_enable
- || u->cm2_params->cm2_luts.lut3d_data.lut3d_src != u->surface->mcm_luts.lut3d_data.lut3d_src) {
- update_flags->bits.mcm_transfer_function_enable_change = 1;
+
+ if (u->cm) {
+ const union dc_plane_cm_flags blend_only_flags = {
+ .bits = {
+ .blend_enable = 1,
+ }
+ };
+
+ if (u->cm->flags.bits.shaper_enable != u->surface->cm.flags.bits.shaper_enable
+ || u->cm->flags.bits.blend_enable != u->surface->cm.flags.bits.blend_enable
+ || u->cm->flags.bits.lut3d_enable != u->surface->cm.flags.bits.lut3d_enable
+ || u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable) {
+ update_bits->mcm_transfer_function_enable_change = 1;
+ elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
+ }
+
+ if ((u->cm->flags.all != blend_only_flags.all && u->cm->flags.all != 0) ||
+ (u->surface->cm.flags.all != blend_only_flags.all && u->surface->cm.flags.all != 0)) {
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
}
- if (update_flags->bits.lut_3d &&
- u->surface->mcm_luts.lut3d_data.lut3d_src != DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
+ if (update_bits->lut_3d &&
+ !u->surface->cm.flags.bits.lut3d_dma_enable) {
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
if (check_config->enable_legacy_fast_update &&
- (update_flags->bits.gamma_change ||
- update_flags->bits.gamut_remap_change ||
- update_flags->bits.input_csc_change ||
- update_flags->bits.cm_hist_change ||
- update_flags->bits.coeff_reduction_change)) {
+ (update_bits->gamma_change ||
+ update_bits->gamut_remap_change ||
+ update_bits->input_csc_change ||
+ update_bits->cm_hist_change ||
+ update_bits->coeff_reduction_change)) {
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
return overall_type;
@@@ -3036,7 -3083,7 +3083,7 @@@ static void force_immediate_gsl_plane_f
if (has_flip_immediate_plane && surface_count > 1) {
for (i = 0; i < surface_count; i++) {
if (updates[i].surface->flip_immediate)
- updates[i].surface->update_flags.bits.addr_update = 1;
+ updates[i].surface->update_bits.addr_update = 1;
}
}
}
@@@ -3191,9 -3238,9 +3238,9 @@@ struct surface_update_descriptor dc_che
struct dc_stream_update *stream_update)
{
if (stream_update)
- stream_update->stream->update_flags.raw = 0;
+ stream_update_flags_clear(&stream_update->stream->update_flags);
for (int i = 0; i < surface_count; i++)
- updates[i].surface->update_flags.raw = 0;
+ dc_pipe_update_bits_clear(&updates[i].surface->update_bits);
return check_update_surfaces_for_stream(check_config, updates, surface_count, stream_update);
}
@@@ -3304,24 -3351,55 +3351,55 @@@ static void copy_surface_update_to_plan
sizeof(struct dc_transfer_func_distributed_points));
}
- if (srf_update->cm2_params) {
- surface->mcm_shaper_3dlut_setting = srf_update->cm2_params->component_settings.shaper_3dlut_setting;
- surface->mcm_lut1d_enable = srf_update->cm2_params->component_settings.lut1d_enable;
- surface->mcm_luts = srf_update->cm2_params->cm2_luts;
+ /* Shaper, 3DLUT, 1DLUT */
+ if (srf_update->cm) {
+ struct kref refcount = surface->cm.refcount;
+
+ memcpy(&surface->cm, srf_update->cm, sizeof(surface->cm));
+ surface->cm.refcount = refcount;
+
+ #ifndef TRIM_CM2
+ /* Populate mcm_luts from cm for legacy consumers (dml2, hwseq) */
+ surface->mcm_luts.lut1d_func = &surface->cm.blend_func;
+ surface->mcm_luts.shaper = &surface->cm.shaper_func;
+ if (srf_update->cm->flags.bits.lut3d_dma_enable) {
+ surface->mcm_luts.lut3d_data.lut3d_src = DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM;
+ surface->mcm_luts.lut3d_data.gpu_mem_params.addr = surface->cm.lut3d_dma.addr;
+ surface->mcm_luts.lut3d_data.gpu_mem_params.layout =
+ (surface->cm.lut3d_dma.swizzle == CM_LUT_3D_SWIZZLE_LINEAR_RGB) ?
+ DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB :
+ (surface->cm.lut3d_dma.swizzle == CM_LUT_3D_SWIZZLE_LINEAR_BGR) ?
+ DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR :
+ DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR;
+ surface->mcm_luts.lut3d_data.gpu_mem_params.format_params.format =
+ (surface->cm.lut3d_dma.format == CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB) ?
+ DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB :
+ (surface->cm.lut3d_dma.format == CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB) ?
+ DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB :
+ DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10;
+ surface->mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias =
+ surface->cm.lut3d_dma.bias;
+ surface->mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale =
+ surface->cm.lut3d_dma.scale;
+ surface->mcm_luts.lut3d_data.gpu_mem_params.component_order =
+ DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA;
+ surface->mcm_luts.lut3d_data.gpu_mem_params.size = DC_CM2_GPU_MEM_SIZE_TRANSFORMED;
+ surface->mcm_luts.lut3d_data.mpc_3dlut_enable = (srf_update->cm->flags.bits.lut3d_enable != 0);
+ } else {
+ surface->mcm_luts.lut3d_data.lut3d_src = DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM;
+ surface->mcm_luts.lut3d_data.lut3d_func = &surface->cm.lut3d_func;
+ }
+
+ if (srf_update->cm->flags.bits.shaper_enable &&
+ srf_update->cm->flags.bits.lut3d_enable)
+ surface->mcm_shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT;
+ else if (srf_update->cm->flags.bits.shaper_enable)
+ surface->mcm_shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER;
+ else
+ surface->mcm_shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL;
+ #endif /* TRIM_CM2 */
}
- if (srf_update->func_shaper) {
- memcpy(&surface->in_shaper_func, srf_update->func_shaper,
- sizeof(surface->in_shaper_func));
-
- if (surface->mcm_shaper_3dlut_setting >= DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER)
- surface->mcm_luts.shaper = &surface->in_shaper_func;
- }
-
- if (srf_update->lut3d_func)
- memcpy(&surface->lut3d_func, srf_update->lut3d_func,
- sizeof(surface->lut3d_func));
-
if (srf_update->hdr_mult.value)
surface->hdr_mult =
srf_update->hdr_mult;
@@@ -3330,15 -3408,10 +3408,10 @@@
surface->sdr_white_level_nits =
srf_update->sdr_white_level_nits;
- if (srf_update->blend_tf) {
- memcpy(&surface->blend_tf, srf_update->blend_tf,
- sizeof(surface->blend_tf));
-
- if (surface->mcm_lut1d_enable)
- surface->mcm_luts.lut1d_func = &surface->blend_tf;
- }
-
- if (srf_update->cm2_params || srf_update->blend_tf)
+ if (srf_update->cm &&
+ (srf_update->cm->flags.bits.blend_enable ||
+ srf_update->cm->flags.bits.shaper_enable ||
+ srf_update->cm->flags.bits.lut3d_enable))
surface->lut_bank_a = !surface->lut_bank_a;
if (srf_update->input_csc_color_matrix)
@@@ -3714,11 -3787,11 +3787,11 @@@ static bool update_planes_and_stream_st
if (update_type == UPDATE_TYPE_FULL) {
if (stream_update) {
uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed;
- stream_update->stream->update_flags.raw = 0xFFFFFFFF;
+ stream_update_flags_set_full(&stream_update->stream->update_flags);
stream_update->stream->update_flags.bits.dsc_changed = dsc_changed;
}
for (i = 0; i < surface_count; i++)
- srf_updates[i].surface->update_flags.raw = 0xFFFFFFFF;
+ dc_pipe_update_bits_set_full(&srf_updates[i].surface->update_bits);
}
if (update_type >= update_surface_trace_level)
@@@ -3767,7 -3840,7 +3840,7 @@@
if (update_type != UPDATE_TYPE_MED)
continue;
- if (surface->update_flags.bits.position_change) {
+ if (surface->update_bits.position_change) {
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
@@@ -4205,8 -4278,8 +4278,8 @@@ static void commit_planes_do_stream_upd
hwss_add_dc_set_optimized_required(&seq_state, dc, true);
} else {
- if (get_seamless_boot_stream_count(context) == 0)
- hwss_add_prepare_bandwidth(&seq_state, dc, dc->current_state);
+ if (get_seamless_boot_stream_count(context) == 0 && dc->hwss.prepare_bandwidth_sequence)
+ dc->hwss.prepare_bandwidth_sequence(dc, dc->current_state, &seq_state);
hwss_add_link_set_dpms_on(&seq_state, dc->current_state, dpms_pipe_ctx);
}
} else if (pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && stream_update->output_color_space
@@@ -4550,14 -4623,23 +4623,23 @@@ static void build_dmub_update_dirty_rec
}
}
- static bool check_address_only_update(union surface_update_flags update_flags)
+ /**
+ * dc_check_address_only_update - Check if addr_update is the sole flag set
+ *
+ * @update_bits: The pipe update bits to check
+ *
+ * Determines whether an update contains only an address change with no other
+ * pending updates.
+ *
+ * Return: %true if addr_update is the sole bit set, %false otherwise.
+ */
+ bool dc_check_address_only_update(struct pipe_update_bits update_bits)
{
- union surface_update_flags addr_only_update_flags;
- addr_only_update_flags.raw = 0;
- addr_only_update_flags.bits.addr_update = 1;
+ struct pipe_update_bits check = update_bits; /* 1. Copy all flags from input */
- return update_flags.bits.addr_update &&
- !(update_flags.raw & ~addr_only_update_flags.raw);
+ check.addr_update = 0; /* 2. Zero the addr_update bit in the copy */
+ return update_bits.addr_update && /* 3. Check addr_update was set in original */
+ !dc_pipe_update_bits_is_any_set(&check); /* 4. Check no other bits remain in the copy */
}
/**
@@@ -4617,7 -4699,7 +4699,7 @@@ static void commit_plane_for_stream_off
continue;
/* update pipe context for plane */
- if (pipe_ctx->plane_state->update_flags.bits.addr_update)
+ if (pipe_ctx->plane_state->update_bits.addr_update)
dc->hwss.update_plane_addr(dc, pipe_ctx);
}
}
@@@ -4655,8 -4737,8 +4737,8 @@@ static void commit_planes_for_stream_fa
should_offload_fams2_flip = true;
for (i = 0; i < surface_count; i++) {
if (srf_updates[i].surface &&
- srf_updates[i].surface->update_flags.raw &&
- !check_address_only_update(srf_updates[i].surface->update_flags)) {
+ dc_pipe_update_bits_is_any_set(&srf_updates[i].surface->update_bits) &&
+ !dc_check_address_only_update(srf_updates[i].surface->update_bits)) {
/* more than address update, need to acquire FAMS2 lock */
should_offload_fams2_flip = false;
break;
@@@ -4747,7 -4829,7 +4829,7 @@@
* so no need to clear here.
*/
if (top_pipe_to_program->stream)
- top_pipe_to_program->stream->update_flags.raw = 0;
+ stream_update_flags_clear(&top_pipe_to_program->stream->update_flags);
}
static void commit_planes_for_stream(struct dc *dc,
@@@ -5073,11 -5155,9 +5155,9 @@@
if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
continue;
- if (srf_updates[i].cm2_params &&
- srf_updates[i].cm2_params->cm2_luts.lut3d_data.lut3d_src ==
- DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM &&
- srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting ==
- DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT &&
+ if (srf_updates[i].cm &&
+ srf_updates[i].cm->flags.bits.lut3d_enable &&
+ srf_updates[i].cm->flags.bits.lut3d_dma_enable &&
dc->hwss.trigger_3dlut_dma_load)
dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx);
@@@ -5087,7 -5167,7 +5167,7 @@@
dc->hwss.program_triplebuffer(
dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
}
- if (pipe_ctx->plane_state->update_flags.bits.addr_update)
+ if (pipe_ctx->plane_state->update_bits.addr_update)
dc->hwss.update_plane_addr(dc, pipe_ctx);
}
}
@@@ -5178,7 -5258,7 +5258,7 @@@
if (pipe_ctx->bottom_pipe || pipe_ctx->next_odm_pipe ||
!pipe_ctx->stream || !should_update_pipe_for_stream(context, pipe_ctx, stream) ||
- !pipe_ctx->plane_state->update_flags.bits.addr_update ||
+ !pipe_ctx->plane_state->update_bits.addr_update ||
pipe_ctx->plane_state->skip_manual_trigger)
continue;
@@@ -5617,7 -5697,7 +5697,7 @@@ static bool commit_minimal_transition_s
/* force full surface update */
for (i = 0; i < dc->current_state->stream_count; i++) {
for (j = 0; j < (unsigned int)dc->current_state->stream_status[i].plane_count; j++) {
- dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF;
+ dc_pipe_update_bits_set_full(&dc->current_state->stream_status[i].plane_states[j]->update_bits);
}
}
@@@ -5792,14 -5872,9 +5872,9 @@@ static bool full_update_required
(srf_updates[i].sdr_white_level_nits &&
srf_updates[i].sdr_white_level_nits != srf_updates->surface->sdr_white_level_nits) ||
srf_updates[i].in_transfer_func ||
- srf_updates[i].func_shaper ||
- srf_updates[i].lut3d_func ||
srf_updates[i].surface->force_full_update ||
(srf_updates[i].flip_addr &&
- srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) ||
- (srf_updates[i].cm2_params &&
- (srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting != srf_updates[i].surface->mcm_shaper_3dlut_setting ||
- srf_updates[i].cm2_params->component_settings.lut1d_enable != srf_updates[i].surface->mcm_lut1d_enable))))
+ srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface)))
return true;
}
@@@ -6063,17 -6138,17 +6138,17 @@@ static bool update_planes_and_stream_v3
return true;
}
- static void clear_update_flags(struct dc_surface_update *srf_updates,
+ static void clear_update_bits(struct dc_surface_update *srf_updates,
int surface_count, struct dc_stream_state *stream)
{
int i;
if (stream)
- stream->update_flags.raw = 0;
+ stream_update_flags_clear(&stream->update_flags);
for (i = 0; i < surface_count; i++)
if (srf_updates[i].surface)
- srf_updates[i].surface->update_flags.raw = 0;
+ dc_pipe_update_bits_clear(&srf_updates[i].surface->update_bits);
}
bool dc_update_planes_and_stream(struct dc *dc,
@@@ -6125,7 -6200,7 +6200,7 @@@ void dc_commit_updates_for_stream(struc
}
if (ret && dc->ctx->dce_version >= DCN_VERSION_3_2)
- clear_update_flags(srf_updates, surface_count, stream);
+ clear_update_bits(srf_updates, surface_count, stream);
}
uint8_t dc_get_current_stream_count(struct dc *dc)
@@@ -6165,6 -6240,115 +6240,6 @@@ void dc_interrupt_ack(struct dc *dc, en
dal_irq_service_ack(dc->res_pool->irqs, src);
}
-/* Preserve this tg if a physical link is still lighting a present display */
-static bool should_preserve_tg(struct dc *dc, struct timing_generator *tg)
-{
- unsigned int i, j;
-
- /* Check if a physical link is lighting this tg */
- for (i = 0; i < dc->link_count; i++) {
- struct dc_link *link = dc->links[i];
- int fe;
-
- if (!link || link->ep_type != DISPLAY_ENDPOINT_PHY ||
- !link->link_enc ||
- !link->link_enc->funcs->is_dig_enabled ||
- !link->link_enc->funcs->is_dig_enabled(link->link_enc) ||
- !link->link_enc->funcs->get_dig_frontend)
- continue;
-
- /* Get the DIG front-end this link's encoder drives; skip if none */
- fe = link->link_enc->funcs->get_dig_frontend(link->link_enc);
- if (fe == ENGINE_ID_UNKNOWN)
- continue;
-
- /* Find the stream encoder bound to this link's front-end */
- for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
- struct stream_encoder *se = dc->res_pool->stream_enc[j];
-
- /* Skip unless this stream encoder feeds our front-end and drives this tg */
- if (se->id != fe || !se->funcs->dig_source_otg ||
- (int)se->funcs->dig_source_otg(se) != tg->inst)
- continue;
-
- /* This link drives the OTG: keep a seamless-boot eDP, or
- * any external link whose sink is still connected.
- */
- if (link->connector_signal == SIGNAL_TYPE_EDP)
- return true;
- if (link->link_enc->funcs->get_hpd_state &&
- dc->link_srv->get_hpd_state(link))
- return true;
- }
- }
-
- return false;
-}
-
-/*
- * GOP/vBIOS may leave an OPTC enabled for a display present at power-on but no
- * longer driven (e.g. external DP unplugged at boot). Such a dangling pipe keeps
- * DCN out of idle and blocks s0i3. If nothing needs to survive (no committed
- * stream or seamless-boot eDP) and no sink is still connected, power down all hw
- * blocks.
- */
-void dc_disable_dangling_timing_generators(struct dc *dc)
-{
- struct dce_hwseq *hws = dc->hwseq;
- bool any_dangling = false;
- bool any_preserved = false;
- bool any_connected = false;
- unsigned int i;
-
- /* No real hw to touch on a virtual/emulated environment */
- if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
- return;
-
- /* Wake hw out of IPS before reading/touching tg state */
- dc_exit_ips_for_hw_access(dc);
-
- /* Classify every enabled tg as either to-preserve or dangling */
- for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
- struct timing_generator *tg = dc->res_pool->timing_generators[i];
-
- if (!tg || !tg->funcs->is_tg_enabled ||
- !tg->funcs->is_tg_enabled(tg))
- continue;
-
- if (should_preserve_tg(dc, tg))
- any_preserved = true;
- else
- any_dangling = true;
- }
-
- /* A physically connected sink (HPD asserted) will be re-lit by a
- * subsequent atomic commit. For that case we don't call the global
- * power_down().
- */
- for (i = 0; i < dc->link_count; i++) {
- struct dc_link *link = dc->links[i];
-
- if (link && link->ep_type == DISPLAY_ENDPOINT_PHY &&
- link->link_enc && link->link_enc->funcs &&
- link->link_enc->funcs->get_hpd_state &&
- dc->link_srv->get_hpd_state(link)) {
- any_connected = true;
- break;
- }
- }
-
- if (!any_dangling)
- return;
-
- if (!any_preserved && !any_connected && hws && hws->funcs.power_down) {
- /* Truly headless / all sinks unplugged: nothing to preserve */
- DC_LOG_DC("%s: powering down dangling hw blocks to allow idle\n",
- __func__);
- hws->funcs.power_down(dc);
- return;
- }
-}
-
/*
* dc_get_flip_pending_on_otg() - Check if a GRPH_FLIP is still pending on OTG
*
@@@ -6183,7 -6367,7 +6258,7 @@@
bool dc_get_flip_pending_on_otg(struct dc *dc, int otg_inst)
{
bool flip_pending = false;
- int i;
+ unsigned int i;
if (!dc || !dc->current_state)
return false;
@@@ -7587,7 -7771,7 +7662,7 @@@ bool dc_capture_register_software_state
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
/* MPCC blending tree and mode control - capture actual blend configuration */
- state->mpc.mpcc_mode[i] = (plane_state->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0;
+ state->mpc.mpcc_mode[i] = (plane_state->cm.blend_func.type != TF_TYPE_BYPASS) ? 1 : 0;
state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0;
state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0;
state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */
@@@ -7920,7 -8104,7 +7995,7 @@@ struct dc_update_scratch_space
struct dc_stream_state *stream;
struct dc_stream_update *stream_update;
bool update_v3;
- bool do_clear_update_flags;
+ bool do_clear_update_bits;
enum surface_update_type update_type;
struct dc_state *new_context;
enum update_v3_flow flow;
@@@ -7963,8 -8147,8 +8038,8 @@@ static bool update_planes_and_stream_cl
const struct dc_update_scratch_space *scratch
)
{
- if (scratch->do_clear_update_flags)
- clear_update_flags(scratch->surface_updates, scratch->surface_count, scratch->stream);
+ if (scratch->do_clear_update_bits)
+ clear_update_bits(scratch->surface_updates, scratch->surface_count, scratch->stream);
return false;
}
@@@ -8218,8 -8402,8 +8293,8 @@@ static bool update_planes_and_stream_cl
ASSERT(false);
}
- if (scratch->do_clear_update_flags)
- clear_update_flags(scratch->surface_updates, scratch->surface_count, scratch->stream);
+ if (scratch->do_clear_update_bits)
+ clear_update_bits(scratch->surface_updates, scratch->surface_count, scratch->stream);
return false;
}
@@@ -8242,7 -8426,7 +8317,7 @@@ struct dc_update_scratch_space *dc_upda
.stream = stream,
.stream_update = stream_update,
.update_v3 = version >= DCN_VERSION_4_01 || version == DCN_VERSION_3_2 || version == DCN_VERSION_3_21,
- .do_clear_update_flags = version >= DCN_VERSION_1_0,
+ .do_clear_update_bits = version >= DCN_VERSION_1_0,
};
return scratch;
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-07-17 14:40 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-07-17 14:40 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Jesse Zhang, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 14782 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
between commits:
614e8a989d462 ("drm/amdgpu: trigger GPU recovery when userq destroy fails to unmap a hung queue")
cee666427f280 ("drm/amdgpu/userq: fix indefinite fence wait during GPU reset")
from the drm-fixes tree and commits:
8396b9de4198a ("drm/amdgpu: trigger GPU recovery when userq destroy fails to unmap a hung queue")
9102b39fa924d ("drm/amdgpu/userq: fix indefinite fence wait during GPU reset")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 572f2949cb64e,babaabe2d891d..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@@ -33,6 -33,7 +33,7 @@@
#include "amdgpu_userq.h"
#include "amdgpu_hmm.h"
#include "amdgpu_userq_fence.h"
+ #include "amdgpu_trace.h"
u32 amdgpu_userq_get_supported_ip_mask(struct amdgpu_device *adev)
{
@@@ -88,14 -89,7 +89,7 @@@ static void amdgpu_userq_mgr_reset_work
container_of(work, struct amdgpu_userq_mgr,
reset_work);
struct amdgpu_device *adev = uq_mgr->adev;
- const int queue_types[] = {
- AMDGPU_RING_TYPE_COMPUTE,
- AMDGPU_RING_TYPE_GFX,
- AMDGPU_RING_TYPE_SDMA
- };
- const int num_queue_types = ARRAY_SIZE(queue_types);
- bool gpu_reset = false;
- int i, r;
+ struct amdgpu_reset_context reset_context;
if (unlikely(adev->debug_disable_gpu_ring_reset)) {
dev_err(adev->dev, "userq reset disabled by debug mask\n");
@@@ -109,42 -103,15 +103,15 @@@
if (!amdgpu_gpu_recovery)
return;
- /*
- * Iterate through all queue types to detect and reset problematic queues
- * Process each queue type in the defined order
- */
- for (i = 0; i < num_queue_types; i++) {
- int ring_type = queue_types[i];
- const struct amdgpu_userq_funcs *funcs =
- adev->userq_funcs[ring_type];
+ memset(&reset_context, 0, sizeof(reset_context));
- if (!amdgpu_userq_is_reset_type_supported(adev, ring_type,
- AMDGPU_RESET_TYPE_PER_QUEUE))
- continue;
+ reset_context.method = AMD_RESET_METHOD_NONE;
+ reset_context.reset_req_dev = adev;
+ reset_context.src = AMDGPU_RESET_SRC_USERQ;
+ set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
+ /*set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);*/
- if (atomic_read(&uq_mgr->userq_count[ring_type]) > 0 &&
- funcs && funcs->detect_and_reset) {
- r = funcs->detect_and_reset(adev, ring_type);
- if (r) {
- gpu_reset = true;
- break;
- }
- }
- }
-
- if (gpu_reset) {
- struct amdgpu_reset_context reset_context;
-
- memset(&reset_context, 0, sizeof(reset_context));
-
- reset_context.method = AMD_RESET_METHOD_NONE;
- reset_context.reset_req_dev = adev;
- reset_context.src = AMDGPU_RESET_SRC_USERQ;
- set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
- /*set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);*/
-
- amdgpu_device_gpu_recover(adev, NULL, &reset_context);
- }
+ amdgpu_device_gpu_recover(adev, NULL, &reset_context);
}
static void amdgpu_userq_hang_detect_work(struct work_struct *work)
@@@ -152,12 -119,45 +119,45 @@@
struct amdgpu_usermode_queue *queue =
container_of(work, struct amdgpu_usermode_queue,
hang_detect_work.work);
+ struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
+ struct amdgpu_device *adev = uq_mgr->adev;
+ const struct amdgpu_userq_funcs *userq_funcs =
+ adev->userq_funcs[queue->queue_type];
+ bool gpu_reset = false;
+
+ if (unlikely(adev->debug_disable_gpu_ring_reset)) {
+ dev_err(adev->dev, "userq reset disabled by debug mask\n");
+ return;
+ }
+
+ /*
+ * If GPU recovery feature is disabled system-wide,
+ * skip all reset detection logic
+ */
+ if (!amdgpu_gpu_recovery)
+ return;
+
+ if (amdgpu_userq_is_reset_type_supported(adev, queue->queue_type,
+ AMDGPU_RESET_TYPE_PER_QUEUE)) {
+ int r;
+
+ if (queue->queue_type == AMDGPU_HW_IP_COMPUTE)
+ r = amdgpu_gfx_reset_mes_compute(adev, NULL, NULL,
+ queue, NULL, NULL);
+ else
+ r = userq_funcs->reset(queue);
+ if (r)
+ gpu_reset = true;
+ } else {
+ gpu_reset = true;
+ }
/*
* Don't schedule the work here! Scheduling or queue work from one reset
* handler to another is illegal if you don't take extra precautions!
*/
- amdgpu_userq_mgr_reset_work(&queue->userq_mgr->reset_work);
+ if (gpu_reset)
+ amdgpu_userq_mgr_reset_work(&queue->userq_mgr->reset_work);
}
/*
@@@ -293,11 -293,15 +293,15 @@@ static int amdgpu_userq_preempt_helper(
int r;
if (queue->state == AMDGPU_USERQ_STATE_MAPPED) {
+ trace_amdgpu_userq_state_start(queue);
+
r = userq_funcs->preempt(queue);
if (r) {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_HUNG);
queue->state = AMDGPU_USERQ_STATE_HUNG;
return r;
} else {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_PREEMPTED);
queue->state = AMDGPU_USERQ_STATE_PREEMPTED;
}
}
@@@ -313,10 -317,14 +317,14 @@@ static int amdgpu_userq_restore_helper(
int r = 0;
if (queue->state == AMDGPU_USERQ_STATE_PREEMPTED) {
+ trace_amdgpu_userq_state_start(queue);
+
r = userq_funcs->restore(queue);
if (r) {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_HUNG);
queue->state = AMDGPU_USERQ_STATE_HUNG;
} else {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_MAPPED);
queue->state = AMDGPU_USERQ_STATE_MAPPED;
}
}
@@@ -334,12 -342,15 +342,15 @@@ static int amdgpu_userq_unmap_helper(st
if ((queue->state == AMDGPU_USERQ_STATE_MAPPED) ||
(queue->state == AMDGPU_USERQ_STATE_PREEMPTED)) {
+ trace_amdgpu_userq_state_start(queue);
r = userq_funcs->unmap(queue);
if (r) {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_HUNG);
queue->state = AMDGPU_USERQ_STATE_HUNG;
return r;
} else {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_UNMAPPED);
queue->state = AMDGPU_USERQ_STATE_UNMAPPED;
}
}
@@@ -356,11 -367,15 +367,15 @@@ static int amdgpu_userq_map_helper(stru
int r;
if (queue->state == AMDGPU_USERQ_STATE_UNMAPPED) {
+ trace_amdgpu_userq_state_start(queue);
+
r = userq_funcs->map(queue);
if (r) {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_HUNG);
queue->state = AMDGPU_USERQ_STATE_HUNG;
return r;
} else {
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_MAPPED);
queue->state = AMDGPU_USERQ_STATE_MAPPED;
}
}
@@@ -507,6 -522,8 +522,8 @@@ amdgpu_userq_destroy(struct amdgpu_user
const struct amdgpu_userq_funcs *uq_funcs = adev->userq_funcs[queue->queue_type];
int r = 0;
+ trace_amdgpu_userq_destroy_start(queue);
+
cancel_delayed_work_sync(&uq_mgr->resume_work);
/* Cancel any pending hang detection work and cleanup */
@@@ -541,6 -558,7 +558,7 @@@
amdgpu_bo_unreserve(queue->db_obj.obj);
amdgpu_bo_unref(&queue->db_obj.obj);
+ trace_amdgpu_userq_destroy_end(queue, r);
kfree(queue);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@@ -638,6 -656,8 +656,8 @@@ amdgpu_userq_create(struct drm_file *fi
queue->queue_type = args->in.ip_type;
queue->vm = &fpriv->vm;
queue->priority = priority;
+ queue->xcp_id = (fpriv->xcp_id != AMDGPU_XCP_NO_PARTITION) ?
+ fpriv->xcp_id : 0;
queue->userq_mgr = uq_mgr;
INIT_DELAYED_WORK(&queue->hang_detect_work,
amdgpu_userq_hang_detect_work);
@@@ -680,6 -700,8 +700,8 @@@
}
queue->doorbell_index = index;
+ queue->doorbell_offset = (u32)args->in.doorbell_offset;
+ trace_amdgpu_userq_create_start(queue);
r = uq_funcs->mqd_create(queue, &args->in);
if (r) {
drm_file_err(uq_mgr->file, "Failed to create Queue\n");
@@@ -703,6 -725,7 +725,7 @@@
r = amdgpu_userq_map_helper(queue);
if (r) {
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
+ trace_amdgpu_userq_create_end(queue, r);
mutex_unlock(&uq_mgr->userq_mutex);
goto erase_doorbell;
}
@@@ -719,11 -742,13 +742,13 @@@
* This drops the last reference which should take care of
* all cleanup.
*/
+ trace_amdgpu_userq_create_end(queue, r);
amdgpu_userq_put(queue);
return r;
}
amdgpu_debugfs_userq_init(filp, queue, qid);
+ trace_amdgpu_userq_create_end(queue, 0);
args->out.queue_id = qid;
return 0;
@@@ -739,6 -764,7 +764,7 @@@ clean_doorbell_bo
free_fence_drv:
amdgpu_userq_fence_driver_free(queue);
free_queue:
+ trace_amdgpu_userq_create_end(queue, r);
kfree(queue);
err_pm_runtime:
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@@ -871,16 -897,10 +897,10 @@@ int amdgpu_userq_ioctl(struct drm_devic
static int
amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
{
- struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
- struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_usermode_queue *queue;
unsigned long queue_id;
int ret = 0, r;
-
- if (amdgpu_bo_reserve(vm->root.bo, false))
- return false;
-
mutex_lock(&uq_mgr->userq_mutex);
/* Resume all the queues for this process */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
@@@ -888,6 -908,7 +908,7 @@@
if (!amdgpu_userq_buffer_vas_mapped(queue)) {
drm_file_err(uq_mgr->file,
"trying restore queue without va mapping\n");
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_INVALID_VA);
queue->state = AMDGPU_USERQ_STATE_INVALID_VA;
continue;
}
@@@ -895,10 -916,8 +916,8 @@@
r = amdgpu_userq_map_helper(queue);
if (r)
ret = r;
-
}
mutex_unlock(&uq_mgr->userq_mutex);
- amdgpu_bo_unreserve(vm->root.bo);
if (ret)
drm_file_err(uq_mgr->file,
@@@ -932,7 -951,8 +951,8 @@@ amdgpu_userq_bo_validate(struct amdgpu_
spin_unlock(&vm->individual_lock);
bo = bo_va->base.bo;
- ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 2);
+ ret = drm_exec_prepare_obj(exec, &bo->tbo.base,
+ TTM_NUM_MOVE_FENCES + 1);
if (unlikely(ret))
return ret;
@@@ -955,7 -975,7 +975,7 @@@
/* Make sure the whole VM is ready to be used */
static int
- amdgpu_userq_vm_validate(struct amdgpu_userq_mgr *uq_mgr)
+ amdgpu_userq_vm_validate_and_restore_queue(struct amdgpu_userq_mgr *uq_mgr)
{
struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
bool invalidated = false, new_addition = false;
@@@ -1081,8 -1101,12 +1101,12 @@@ retry_lock
dma_fence_wait(vm->last_update, false);
ret = amdgpu_evf_mgr_rearm(&fpriv->evf_mgr, &exec);
- if (ret)
+ if (ret) {
drm_file_err(uq_mgr->file, "Failed to replace eviction fence\n");
+ goto unlock_all;
+ }
+
+ ret = amdgpu_userq_restore_all(uq_mgr);
unlock_all:
drm_exec_fini(&exec);
@@@ -1108,18 -1132,34 +1132,34 @@@ static void amdgpu_userq_restore_worker
if (!dma_fence_is_signaled(ev_fence))
goto put_fence;
- ret = amdgpu_userq_vm_validate(uq_mgr);
+ ret = amdgpu_userq_vm_validate_and_restore_queue(uq_mgr);
if (ret) {
drm_file_err(uq_mgr->file, "Failed to validate BOs to restore ret=%d\n", ret);
goto put_fence;
}
- amdgpu_userq_restore_all(uq_mgr);
-
put_fence:
dma_fence_put(ev_fence);
}
+ void amdgpu_userq_process_reset_irq(struct amdgpu_device *adev,
+ u32 pasid, u32 doorbell_offset)
+ {
+ struct xarray *xa = &adev->userq_doorbell_xa;
+ struct amdgpu_usermode_queue *queue;
+ unsigned long flags, idx;
+
+ xa_lock_irqsave(xa, flags);
+ xa_for_each(xa, idx, queue) {
+ if (queue->vm && queue->vm->pasid == pasid &&
+ queue->doorbell_offset == doorbell_offset) {
+ amdgpu_userq_start_hang_detect_work(queue);
+ break;
+ }
+ }
+ xa_unlock_irqrestore(xa, flags);
+ }
+
static int
amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
{
@@@ -1175,6 -1215,7 +1215,7 @@@ int amdgpu_userq_mgr_init(struct amdgpu
xa_init_flags(&userq_mgr->userq_xa, XA_FLAGS_ALLOC);
userq_mgr->adev = adev;
userq_mgr->file = file_priv;
+ mutex_init(&userq_mgr->proc_ctx_lock);
INIT_DELAYED_WORK(&userq_mgr->resume_work, amdgpu_userq_restore_worker);
INIT_WORK(&userq_mgr->reset_work, amdgpu_userq_mgr_reset_work);
@@@ -1228,6 -1269,11 +1269,11 @@@ void amdgpu_userq_mgr_fini(struct amdgp
*/
cancel_work_sync(&userq_mgr->reset_work);
+ amdgpu_bo_free_kernel(&userq_mgr->proc_ctx_obj.obj,
+ &userq_mgr->proc_ctx_obj.gpu_addr,
+ &userq_mgr->proc_ctx_obj.cpu_ptr);
+
+ mutex_destroy(&userq_mgr->proc_ctx_lock);
mutex_destroy(&userq_mgr->userq_mutex);
}
@@@ -1377,12 -1423,14 +1423,14 @@@ void amdgpu_userq_pre_reset(struct amdg
/* TODO: We probably need a new lock for the queue state */
xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
if (queue->state == AMDGPU_USERQ_STATE_MAPPED) {
+ trace_amdgpu_userq_state_start(queue);
userq_funcs = adev->userq_funcs[queue->queue_type];
userq_funcs->unmap(queue);
/* just mark all queues as hung at this point.
* if unmap succeeds, we could map again
* in amdgpu_userq_post_reset() if vram is not lost
*/
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_HUNG);
queue->state = AMDGPU_USERQ_STATE_HUNG;
}
/* Force-complete any pending fence regardless of queue state so
@@@ -1406,6 -1454,8 +1454,8 @@@ int amdgpu_userq_post_reset(struct amdg
xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
if (queue->state == AMDGPU_USERQ_STATE_HUNG && !vram_lost) {
+ trace_amdgpu_userq_state_start(queue);
+
userq_funcs = adev->userq_funcs[queue->queue_type];
/* Re-map queue */
r = userq_funcs->map(queue);
@@@ -1413,6 -1463,7 +1463,7 @@@
dev_err(adev->dev, "Failed to remap queue %ld\n", queue_id);
continue;
}
+ trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_MAPPED);
queue->state = AMDGPU_USERQ_STATE_MAPPED;
}
}
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-07-17 14:40 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-07-17 14:40 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Linux Kernel Mailing List, Linux Next Mailing List,
Mario Limonciello
[-- Attachment #1: Type: text/plain, Size: 16124 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
between commit:
8ad5ab4da7db2 ("drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge")
from the drm-fixes tree and commits:
9ceb4e034a327 ("drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge")
a57c68224d739 ("drm/amd: Move dynamic PCIe switching quirks to X86_MATCH_* macros")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index e5f26e5892bac,472e96ae884e5..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@@ -72,8 -72,10 +72,10 @@@
#include "amdgpu_xgmi.h"
#include "amdgpu_ras.h"
+ #include "amdgpu_wb.h"
#include "amdgpu_ras_mgr.h"
#include "amdgpu_pmu.h"
+ #include "amdgpu_smu.h"
#include "amdgpu_fru_eeprom.h"
#include "amdgpu_reset.h"
#include "amdgpu_virt.h"
@@@ -1005,109 -1007,6 +1007,6 @@@ int amdgpu_device_pci_reset(struct amdg
return pci_reset_function(adev->pdev);
}
- /*
- * amdgpu_device_wb_*()
- * Writeback is the method by which the GPU updates special pages in memory
- * with the status of certain GPU events (fences, ring pointers,etc.).
- */
-
- /**
- * amdgpu_device_wb_fini - Disable Writeback and free memory
- *
- * @adev: amdgpu_device pointer
- *
- * Disables Writeback and frees the Writeback memory (all asics).
- * Used at driver shutdown.
- */
- static void amdgpu_device_wb_fini(struct amdgpu_device *adev)
- {
- if (adev->wb.wb_obj) {
- amdgpu_bo_free_kernel(&adev->wb.wb_obj,
- &adev->wb.gpu_addr,
- (void **)&adev->wb.wb);
- adev->wb.wb_obj = NULL;
- }
- }
-
- /**
- * amdgpu_device_wb_init - Init Writeback driver info and allocate memory
- *
- * @adev: amdgpu_device pointer
- *
- * Initializes writeback and allocates writeback memory (all asics).
- * Used at driver startup.
- * Returns 0 on success or an -error on failure.
- */
- static int amdgpu_device_wb_init(struct amdgpu_device *adev)
- {
- int r;
-
- if (adev->wb.wb_obj == NULL) {
- /* AMDGPU_MAX_WB * sizeof(uint32_t) * 8 = AMDGPU_MAX_WB 256bit slots */
- r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t) * 8,
- PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
- &adev->wb.wb_obj, &adev->wb.gpu_addr,
- (void **)&adev->wb.wb);
- if (r) {
- dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
- return r;
- }
-
- adev->wb.num_wb = AMDGPU_MAX_WB;
- memset(&adev->wb.used, 0, sizeof(adev->wb.used));
-
- /* clear wb memory */
- memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);
- }
-
- return 0;
- }
-
- /**
- * amdgpu_device_wb_get - Allocate a wb entry
- *
- * @adev: amdgpu_device pointer
- * @wb: wb index
- *
- * Allocate a wb slot for use by the driver (all asics).
- * Returns 0 on success or -EINVAL on failure.
- */
- int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
- {
- unsigned long flags, offset;
-
- spin_lock_irqsave(&adev->wb.lock, flags);
- offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
- if (offset < adev->wb.num_wb) {
- __set_bit(offset, adev->wb.used);
- spin_unlock_irqrestore(&adev->wb.lock, flags);
- *wb = offset << 3; /* convert to dw offset */
- return 0;
- } else {
- spin_unlock_irqrestore(&adev->wb.lock, flags);
- return -EINVAL;
- }
- }
-
- /**
- * amdgpu_device_wb_free - Free a wb entry
- *
- * @adev: amdgpu_device pointer
- * @wb: wb index
- *
- * Free a wb slot allocated for use by the driver (all asics)
- */
- void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
- {
- unsigned long flags;
-
- wb >>= 3;
- spin_lock_irqsave(&adev->wb.lock, flags);
- if (wb < adev->wb.num_wb)
- __clear_bit(wb, adev->wb.used);
- spin_unlock_irqrestore(&adev->wb.lock, flags);
- }
-
/**
* amdgpu_device_resize_fb_bar - try to resize FB BAR
*
@@@ -1304,37 -1203,44 +1203,44 @@@ bool amdgpu_device_seamless_boot_suppor
return amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0);
}
- /*
- * Intel hosts such as Rocket Lake, Alder Lake, Raptor Lake and Sapphire Rapids
- * don't support dynamic speed switching. Until we have confirmation from Intel
- * that a specific host supports it, it's safer that we keep it disabled for all.
- *
- * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
- * https://gitlab.freedesktop.org/drm/amd/-/issues/2663
- */
- static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev)
- {
#if IS_ENABLED(CONFIG_X86)
- struct cpuinfo_x86 *c = &cpu_data(0);
-
- /* eGPU change speeds based on USB4 fabric conditions */
- if (dev_is_removable(adev->dev))
- return true;
-
- if (c->x86_vendor == X86_VENDOR_INTEL)
- return false;
-
+ static const struct x86_cpu_id amdgpu_pcie_dynamic_switching_quirks[] = {
+ /*
+ * Intel hosts such as Rocket Lake, Alder Lake, Raptor Lake and Sapphire Rapids
+ * don't support dynamic speed switching. Until we have confirmation from Intel
+ * that a specific host supports it, it's safer that we keep it disabled for all.
+ *
+ * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/2663
+ */
+ X86_MATCH_VENDOR_FAM(INTEL, X86_FAMILY_ANY, NULL),
/*
* AMD Ryzen Pinnacle Ridge (Zen+, family 0x17 model 0x08) CPUs don't
* support PCIe dynamic speed switching.
* https://gitlab.freedesktop.org/drm/amd/-/work_items/5436
*/
- if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 0x17 &&
- c->x86_model == 0x08)
+ X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x17, 0x08, NULL),
+ {}
+ };
+
+ static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev)
+ {
+ /* eGPU change speeds based on USB4 fabric conditions */
+ if (dev_is_removable(adev->dev))
+ return true;
+
+ /* Hosts have problems with dynamic speed switching */
+ if (x86_match_cpu(amdgpu_pcie_dynamic_switching_quirks))
return false;
- #endif
+
return true;
}
+ #else
+ static inline bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev)
+ {
+ return true;
+ }
+ #endif
static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
{
@@@ -2140,6 -2046,8 +2046,8 @@@ static int amdgpu_device_ip_early_init(
adev->cg_flags &= amdgpu_cg_mask;
adev->pg_flags &= amdgpu_pg_mask;
+ amdgpu_smu_early_init(adev);
+
return 0;
}
@@@ -2380,10 -2288,10 +2288,10 @@@ static int amdgpu_device_ip_init(struc
r);
goto init_failed;
}
- r = amdgpu_device_wb_init(adev);
+ r = amdgpu_wb_init(adev);
if (r) {
dev_err(adev->dev,
- "amdgpu_device_wb_init failed %d\n", r);
+ "amdgpu_wb_init failed %d\n", r);
goto init_failed;
}
adev->ip_blocks[i].status.hw = true;
@@@ -2915,7 -2823,7 +2823,7 @@@ static int amdgpu_device_ip_fini(struc
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
amdgpu_ucode_free_bo(adev);
amdgpu_free_static_csa(&adev->virt.csa_obj);
- amdgpu_device_wb_fini(adev);
+ amdgpu_wb_fini(adev);
amdgpu_device_mem_scratch_fini(adev);
amdgpu_ib_pool_fini(adev);
amdgpu_seq64_fini(adev);
@@@ -3687,6 -3595,10 +3595,10 @@@ static void amdgpu_device_sys_interface
amdgpu_pm_sysfs_fini(adev);
if (adev->ucode_sysfs_en)
amdgpu_ucode_sysfs_fini(adev);
+
+ amdgpu_discovery_sysfs_fini(adev);
+ amdgpu_preempt_mgr_sysfs_fini(adev);
+
amdgpu_device_attr_sysfs_fini(adev);
amdgpu_fru_sysfs_fini(adev);
@@@ -3783,6 -3695,7 +3695,7 @@@ int amdgpu_device_init(struct amdgpu_de
spin_lock_init(&adev->irq.lock);
+ amdgpu_early_init_rlc_reg_funcs(adev);
amdgpu_device_init_apu_flags(adev);
r = amdgpu_device_check_arguments(adev);
@@@ -4218,6 -4131,7 +4131,7 @@@ void amdgpu_device_fini_hw(struct amdgp
if (adev->mman.initialized)
drain_workqueue(adev->mman.bdev.wq);
+
adev->shutdown = true;
unregister_pm_notifier(&adev->pm_nb);
@@@ -4716,161 -4630,6 +4630,6 @@@ exit
return 0;
}
- /**
- * amdgpu_device_ip_check_soft_reset - did soft reset succeed
- *
- * @adev: amdgpu_device pointer
- *
- * The list of all the hardware IPs that make up the asic is walked and
- * the check_soft_reset callbacks are run. check_soft_reset determines
- * if the asic is still hung or not.
- * Returns true if any of the IPs are still in a hung state, false if not.
- */
- static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev)
- {
- int i;
- bool asic_hang = false;
-
- if (amdgpu_sriov_vf(adev))
- return true;
-
- if (amdgpu_asic_need_full_reset(adev))
- return true;
-
- for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_blocks[i].status.valid)
- continue;
- if (adev->ip_blocks[i].version->funcs->check_soft_reset)
- adev->ip_blocks[i].status.hang =
- adev->ip_blocks[i].version->funcs->check_soft_reset(
- &adev->ip_blocks[i]);
- if (adev->ip_blocks[i].status.hang) {
- dev_info(adev->dev, "IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name);
- asic_hang = true;
- }
- }
- return asic_hang;
- }
-
- /**
- * amdgpu_device_ip_pre_soft_reset - prepare for soft reset
- *
- * @adev: amdgpu_device pointer
- *
- * The list of all the hardware IPs that make up the asic is walked and the
- * pre_soft_reset callbacks are run if the block is hung. pre_soft_reset
- * handles any IP specific hardware or software state changes that are
- * necessary for a soft reset to succeed.
- * Returns 0 on success, negative error code on failure.
- */
- static int amdgpu_device_ip_pre_soft_reset(struct amdgpu_device *adev)
- {
- int i, r = 0;
-
- for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_blocks[i].status.valid)
- continue;
- if (adev->ip_blocks[i].status.hang &&
- adev->ip_blocks[i].version->funcs->pre_soft_reset) {
- r = adev->ip_blocks[i].version->funcs->pre_soft_reset(&adev->ip_blocks[i]);
- if (r)
- return r;
- }
- }
-
- return 0;
- }
-
- /**
- * amdgpu_device_ip_need_full_reset - check if a full asic reset is needed
- *
- * @adev: amdgpu_device pointer
- *
- * Some hardware IPs cannot be soft reset. If they are hung, a full gpu
- * reset is necessary to recover.
- * Returns true if a full asic reset is required, false if not.
- */
- static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev)
- {
- int i;
-
- if (amdgpu_asic_need_full_reset(adev))
- return true;
-
- for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_blocks[i].status.valid)
- continue;
- if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) ||
- (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) ||
- (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) ||
- (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) ||
- adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
- if (adev->ip_blocks[i].status.hang) {
- dev_info(adev->dev, "Some block need full reset!\n");
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * amdgpu_device_ip_soft_reset - do a soft reset
- *
- * @adev: amdgpu_device pointer
- *
- * The list of all the hardware IPs that make up the asic is walked and the
- * soft_reset callbacks are run if the block is hung. soft_reset handles any
- * IP specific hardware or software state changes that are necessary to soft
- * reset the IP.
- * Returns 0 on success, negative error code on failure.
- */
- static int amdgpu_device_ip_soft_reset(struct amdgpu_device *adev)
- {
- int i, r = 0;
-
- for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_blocks[i].status.valid)
- continue;
- if (adev->ip_blocks[i].status.hang &&
- adev->ip_blocks[i].version->funcs->soft_reset) {
- r = adev->ip_blocks[i].version->funcs->soft_reset(&adev->ip_blocks[i]);
- if (r)
- return r;
- }
- }
-
- return 0;
- }
-
- /**
- * amdgpu_device_ip_post_soft_reset - clean up from soft reset
- *
- * @adev: amdgpu_device pointer
- *
- * The list of all the hardware IPs that make up the asic is walked and the
- * post_soft_reset callbacks are run if the asic was hung. post_soft_reset
- * handles any IP specific hardware or software state changes that are
- * necessary after the IP has been soft reset.
- * Returns 0 on success, negative error code on failure.
- */
- static int amdgpu_device_ip_post_soft_reset(struct amdgpu_device *adev)
- {
- int i, r = 0;
-
- for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_blocks[i].status.valid)
- continue;
- if (adev->ip_blocks[i].status.hang &&
- adev->ip_blocks[i].version->funcs->post_soft_reset)
- r = adev->ip_blocks[i].version->funcs->post_soft_reset(&adev->ip_blocks[i]);
- if (r)
- return r;
- }
-
- return 0;
- }
-
/**
* amdgpu_device_reset_sriov - reset ASIC for SR-IOV vf
*
@@@ -5162,20 -4921,7 +4921,7 @@@ int amdgpu_device_pre_asic_reset(struc
/* Don't suspend on bare metal if we are not going to HW reset the ASIC */
if (!amdgpu_sriov_vf(adev)) {
-
- if (!need_full_reset)
- need_full_reset = amdgpu_device_ip_need_full_reset(adev);
-
- if (!need_full_reset && amdgpu_gpu_recovery &&
- amdgpu_device_ip_check_soft_reset(adev)) {
- amdgpu_device_ip_pre_soft_reset(adev);
- r = amdgpu_device_ip_soft_reset(adev);
- amdgpu_device_ip_post_soft_reset(adev);
- if (r || amdgpu_device_ip_check_soft_reset(adev)) {
- dev_info(adev->dev, "soft reset failed, will fallback to full reset!\n");
- need_full_reset = true;
- }
- }
+ need_full_reset = true;
if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) {
dev_info(tmp_adev->dev, "Dumping IP State\n");
@@@ -5628,8 -5374,7 +5374,7 @@@ static void amdgpu_device_halt_activiti
drm_client_dev_suspend(adev_to_drm(tmp_adev));
/* disable ras on ALL IPs */
- if (!need_emergency_restart && !amdgpu_reset_in_dpc(adev) &&
- amdgpu_device_ip_need_full_reset(tmp_adev))
+ if (!need_emergency_restart && !amdgpu_reset_in_dpc(adev))
amdgpu_ras_suspend(tmp_adev);
amdgpu_userq_pre_reset(tmp_adev);
@@@ -6901,7 -6646,7 +6646,7 @@@ ssize_t amdgpu_get_soft_full_reset_mask
if (unlikely(!ring->adev->debug_disable_soft_recovery) &&
!amdgpu_sriov_vf(ring->adev) && ring->funcs->soft_recovery)
- size |= AMDGPU_RESET_TYPE_SOFT_RESET;
+ size |= AMDGPU_RESET_TYPE_SOFT_RECOVERY;
return size;
}
@@@ -6917,8 -6662,8 +6662,8 @@@ ssize_t amdgpu_show_reset_mask(char *bu
}
- if (supported_reset & AMDGPU_RESET_TYPE_SOFT_RESET)
- size += sysfs_emit_at(buf, size, "soft ");
+ if (supported_reset & AMDGPU_RESET_TYPE_SOFT_RECOVERY)
+ size += sysfs_emit_at(buf, size, "soft_recovery ");
if (supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)
size += sysfs_emit_at(buf, size, "queue ");
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-07-17 14:40 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-07-17 14:40 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alessandro Rinaldi, Alex Deucher, Alex Hung, Aurabindo Pillai,
Austin Zheng, Chenyu Chen, Geoffrey McRae, George Zhang,
Harry Wentland, James Lin, Leo Li, Linux Kernel Mailing List,
Linux Next Mailing List, Mario Limonciello, Matthew Schwartz,
Michał Mirosław, Rafal Ostrowski, Thomas Zimmermann,
Timur Kristóf, Tom Chung, WenTao Liang
[-- Attachment #1: Type: text/plain, Size: 277772 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
between commits:
d094bc1f17783 ("drm/amd/display: consolidate DCN vblank/flip handling onto vupdate_no_lock")
d73f4e118dc4c ("drm/amd/display: check GRPH_FLIP status before sending event")
c9ab9622f5b27 ("Revert "drm/amd/display: Restore 5s vbl offdelay for NV3x+ DGPUs"")
d094bc1f17783 ("drm/amd/display: consolidate DCN vblank/flip handling onto vupdate_no_lock")
efd29b1cab549 ("drm/amd/display: set new_stream to NULL after release")
aa377fdcb475c ("drm/amd/display: Force PWM backlight on Lenovo Legion 5 15ARH05")
a991960f8bdc4 ("drm/amd/display: Set native cursor mode for disabled CRTCs")
86e2b8644e92d ("drm/amd/display: Fix backlight max_brightness to match exported range")
from the drm-fixes tree and commits:
99f3af19073b3 ("drm/amd/display: set new_stream to NULL after release")
2f79f0130f828 ("drm/amd/display: Set native cursor mode for disabled CRTCs")
ee186ae23ab0f ("Revert "drm/amd/display: Restore 5s vbl offdelay for NV3x+ DGPUs"")
f64a9be565368 ("drm/amd/display: check GRPH_FLIP status before sending event")
c87e6635d2db0 ("drm/amd/display: consolidate DCN vblank/flip handling onto vupdate_no_lock")
0d6453fd6e17a ("drm/amd/display: Fix DM IRQ teardown races")
a5cd2fbe7b45f ("drm/amd/display/amdgpu_dm: show error names")
163b0b32bfbee ("drm/amd/display: don't re-evaluate cursor mode on cursor plane movement")
98e08a815ef60 ("drm/amd/display: Tear down dangling pipe on boot to fix s0i3")
e4ae30a12aa95 ("drm/amd/display: Fix DM I2C teardown race")
acf97c57d091f ("drm/amd/display: Re-evaluate cursor mode on plane position/size change")
9bcf6af12bacb ("drm/amd/display: hold a vblank ref while writeback is pending")
a24019f6480fa ("drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips")
947e46eb2fb9f ("drm/amdgpu: Delete check_soft_reset() from amd_ip_funcs")
13158e5dbd896 ("drm/amd/display: Fix mem_type change detection for async flips")
c26b643aa31b7 ("drm/amd/display: Add KUnit tests for amdgpu_dm")
c1199393ec559 ("drm/amd/display: Refactor surface_update_flags to flat struct with helpers")
0e967e086e751 ("drm/amd/display: Extract connector and encoder code to amdgpu_dm_connector")
0618dec494157 ("drm/amd/display: Move HPD and IRQ handler code to amdgpu_dm_irq")
4734e045f49d9 ("drm/amd/display: Extract DMUB code to amdgpu_dm_dmub")
ee55bf7d6a63f ("drm/amd/display: Extract audio code to amdgpu_dm_audio")
f5165625b8b27 ("drm/amd/display: Extract backlight code to amdgpu_dm_backlight")
b008c67efb36b ("drm/amd/display: Introduce dc_plane_cm and migrate surface update color path")
60597d2cb2199 ("drm/amd/display: Use handle_hpd_irq_helper for HPD RX")
b7e70a466b3d0 ("drm/amd/display: Add detect reason to handle_hpd_irq_helper")
0fde96e06f1cd ("drm/amd/display: Deprecate DMUB register offload functionality")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 9c564cd5edeea,e7080880b2211..0000000000000
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@@ -66,6 -66,11 +66,11 @@@
#endif
#include "amdgpu_dm_psr.h"
#include "amdgpu_dm_replay.h"
+ #include "amdgpu_dm_backlight.h"
+ #include "amdgpu_dm_audio.h"
+ #include "amdgpu_dm_dmub.h"
+ #include "amdgpu_dm_connector.h"
+ #include "amdgpu_dm_kunit_helpers.h"
#include "ivsrcid/ivsrcid_vislands30.h"
@@@ -94,7 -99,6 +99,6 @@@
#include <drm/drm_mode.h>
#include <drm/drm_utils.h>
#include <drm/drm_vblank.h>
- #include <drm/drm_audio_component.h>
#include <drm/drm_colorop.h>
#include <drm/drm_gem_atomic_helper.h>
@@@ -107,60 -111,9 +111,9 @@@
#include "modules/inc/mod_power.h"
#include "modules/power/power_helpers.h"
- static_assert(AMDGPU_DMUB_NOTIFICATION_MAX == DMUB_NOTIFICATION_MAX, "AMDGPU_DMUB_NOTIFICATION_MAX mismatch");
-
- #define FIRMWARE_RENOIR_DMUB "amdgpu/renoir_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB);
- #define FIRMWARE_SIENNA_CICHLID_DMUB "amdgpu/sienna_cichlid_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID_DMUB);
- #define FIRMWARE_NAVY_FLOUNDER_DMUB "amdgpu/navy_flounder_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER_DMUB);
- #define FIRMWARE_GREEN_SARDINE_DMUB "amdgpu/green_sardine_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_GREEN_SARDINE_DMUB);
- #define FIRMWARE_VANGOGH_DMUB "amdgpu/vangogh_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_VANGOGH_DMUB);
- #define FIRMWARE_DIMGREY_CAVEFISH_DMUB "amdgpu/dimgrey_cavefish_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB);
- #define FIRMWARE_BEIGE_GOBY_DMUB "amdgpu/beige_goby_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB);
- #define FIRMWARE_YELLOW_CARP_DMUB "amdgpu/yellow_carp_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP_DMUB);
- #define FIRMWARE_DCN_314_DMUB "amdgpu/dcn_3_1_4_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_314_DMUB);
- #define FIRMWARE_DCN_315_DMUB "amdgpu/dcn_3_1_5_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_315_DMUB);
- #define FIRMWARE_DCN316_DMUB "amdgpu/dcn_3_1_6_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN316_DMUB);
-
- #define FIRMWARE_DCN_V3_2_0_DMCUB "amdgpu/dcn_3_2_0_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_V3_2_0_DMCUB);
- #define FIRMWARE_DCN_V3_2_1_DMCUB "amdgpu/dcn_3_2_1_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_V3_2_1_DMCUB);
-
- #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin"
MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
-
- #define FIRMWARE_NAVI12_DMCU "amdgpu/navi12_dmcu.bin"
MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU);
- #define FIRMWARE_DCN_35_DMUB "amdgpu/dcn_3_5_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_35_DMUB);
-
- #define FIRMWARE_DCN_351_DMUB "amdgpu/dcn_3_5_1_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_351_DMUB);
-
- #define FIRMWARE_DCN_36_DMUB "amdgpu/dcn_3_6_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_36_DMUB);
-
- #define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB);
-
- #define FIRMWARE_DCN_42_DMUB "amdgpu/dcn_4_2_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
-
- #define FIRMWARE_DCN_42B_DMUB "amdgpu/dcn_4_2_1_dmcub.bin"
- MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB);
-
/**
* DOC: overview
*
@@@ -174,46 -127,7 +127,7 @@@
/* basic init/fini API */
static int amdgpu_dm_init(struct amdgpu_device *adev);
static void amdgpu_dm_fini(struct amdgpu_device *adev);
- static bool is_freesync_video_mode(const struct drm_display_mode *mode, struct amdgpu_dm_connector *aconnector);
static void reset_freesync_config_for_crtc(struct dm_crtc_state *new_crtc_state);
- static struct amdgpu_i2c_adapter *
- create_i2c(struct ddc_service *ddc_service, bool oem);
-
- static enum drm_mode_subconnector get_subconnector_type(struct dc_link *link)
- {
- switch (link->dpcd_caps.dongle_type) {
- case DISPLAY_DONGLE_NONE:
- return DRM_MODE_SUBCONNECTOR_Native;
- case DISPLAY_DONGLE_DP_VGA_CONVERTER:
- return DRM_MODE_SUBCONNECTOR_VGA;
- case DISPLAY_DONGLE_DP_DVI_CONVERTER:
- case DISPLAY_DONGLE_DP_DVI_DONGLE:
- return DRM_MODE_SUBCONNECTOR_DVID;
- case DISPLAY_DONGLE_DP_HDMI_CONVERTER:
- case DISPLAY_DONGLE_DP_HDMI_DONGLE:
- return DRM_MODE_SUBCONNECTOR_HDMIA;
- case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
- default:
- return DRM_MODE_SUBCONNECTOR_Unknown;
- }
- }
-
- static void update_subconnector_property(struct amdgpu_dm_connector *aconnector)
- {
- struct dc_link *link = aconnector->dc_link;
- struct drm_connector *connector = &aconnector->base;
- enum drm_mode_subconnector subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
-
- if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
- return;
-
- if (aconnector->dc_sink)
- subconnector = get_subconnector_type(link);
-
- drm_object_property_set_value(&connector->base,
- connector->dev->mode_config.dp_subconnector_property,
- subconnector);
- }
/*
* initializes drm_device display related structures, based on the information
@@@ -226,32 -140,23 +140,23 @@@ static int amdgpu_dm_initialize_drm_dev
/* removes and deallocates the drm structures, created by the above function */
static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm);
- static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
- struct amdgpu_dm_connector *amdgpu_dm_connector,
- u32 link_index,
- struct amdgpu_encoder *amdgpu_encoder);
- static int amdgpu_dm_encoder_init(struct drm_device *dev,
- struct amdgpu_encoder *aencoder,
- uint32_t link_index);
-
- static int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
-
static int amdgpu_dm_atomic_setup_commit(struct drm_atomic_commit *state);
static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state);
+ static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context);
static int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_atomic_commit *state);
- static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector);
- static void handle_hpd_rx_irq(void *param);
-
- static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
- int bl_idx,
- u32 user_brightness);
-
- static bool
+ STATIC_IFN_KUNIT bool
is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
struct drm_crtc_state *new_crtc_state);
+
+ static inline void amdgpu_dm_exit_ips_for_hw_access(struct dc *dc)
+ {
+ if (dc->ctx->dmub_srv && !dc->ctx->dmub_srv->idle_exit_counter)
+ dc_exit_ips_for_hw_access(dc);
+ }
+
/*
* dm_vblank_get_counter
*
@@@ -332,40 -237,14 +237,14 @@@ static int dm_wait_for_idle(struct amdg
return 0;
}
- static bool dm_check_soft_reset(struct amdgpu_ip_block *ip_block)
- {
- return false;
- }
-
static int dm_soft_reset(struct amdgpu_ip_block *ip_block)
{
/* XXX todo */
return 0;
}
- static struct amdgpu_crtc *
- get_crtc_by_otg_inst(struct amdgpu_device *adev,
- int otg_inst)
- {
- struct drm_device *dev = adev_to_drm(adev);
- struct drm_crtc *crtc;
- struct amdgpu_crtc *amdgpu_crtc;
-
- if (WARN_ON(otg_inst == -1))
- return adev->mode_info.crtcs[0];
-
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- amdgpu_crtc = to_amdgpu_crtc(crtc);
-
- if (amdgpu_crtc->otg_inst == otg_inst)
- return amdgpu_crtc;
- }
-
- return NULL;
- }
-
- static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
- struct dm_crtc_state *new_state)
+ STATIC_IFN_KUNIT bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
+ struct dm_crtc_state *new_state)
{
if (new_state->stream->adjust.timing_adjust_pending)
return true;
@@@ -376,13 -255,14 +255,14 @@@
else
return false;
}
+ EXPORT_IF_KUNIT(is_dc_timing_adjust_needed);
/*
* DC will program planes with their z-order determined by their ordering
* in the dc_surface_updates array. This comparator is used to sort them
* by descending zpos.
*/
- static int dm_plane_layer_index_cmp(const void *a, const void *b)
+ STATIC_IFN_KUNIT int dm_plane_layer_index_cmp(const void *a, const void *b)
{
const struct dc_surface_update *sa = (struct dc_surface_update *)a;
const struct dc_surface_update *sb = (struct dc_surface_update *)b;
@@@ -390,6 -270,7 +270,7 @@@
/* Sort by descending dc_plane layer_index (i.e. normalized_zpos) */
return sb->surface->layer_index - sa->surface->layer_index;
}
+ EXPORT_IF_KUNIT(dm_plane_layer_index_cmp);
/**
* update_planes_and_stream_adapter() - Send planes to be updated in DC
@@@ -430,687 -311,6 +311,6 @@@ static inline bool update_planes_and_st
stream_update);
}
- /**
- * dm_pflip_high_irq() - Handle pageflip interrupt
- * @interrupt_params: ignored
- *
- * Handles the pageflip interrupt by notifying all interested parties
- * that the pageflip has been completed.
- */
- static void dm_pflip_high_irq(void *interrupt_params)
- {
- struct amdgpu_crtc *amdgpu_crtc;
- struct common_irq_params *irq_params = interrupt_params;
- struct amdgpu_device *adev = irq_params->adev;
- struct drm_device *dev = adev_to_drm(adev);
- unsigned long flags;
- struct drm_pending_vblank_event *e;
- u32 vpos, hpos, v_blank_start, v_blank_end;
- bool vrr_active;
-
- amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);
-
- /* IRQ could occur when in initial stage */
- /* TODO work and BO cleanup */
- if (amdgpu_crtc == NULL) {
- drm_dbg_state(dev, "CRTC is null, returning.\n");
- return;
- }
-
- spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-
- if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
- drm_dbg_state(dev,
- "amdgpu_crtc->pflip_status = %d != AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
- amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED,
- amdgpu_crtc->crtc_id, amdgpu_crtc);
- spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
- return;
- }
-
- /* page flip completed. */
- e = amdgpu_crtc->event;
- amdgpu_crtc->event = NULL;
-
- WARN_ON(!e);
-
- vrr_active = amdgpu_dm_crtc_vrr_active_irq(amdgpu_crtc);
-
- /* Fixed refresh rate, or VRR scanout position outside front-porch? */
- if (!vrr_active ||
- !dc_stream_get_scanoutpos(amdgpu_crtc->dm_irq_params.stream, &v_blank_start,
- &v_blank_end, &hpos, &vpos) ||
- (vpos < v_blank_start)) {
- /* Update to correct count and vblank timestamp if racing with
- * vblank irq. This also updates to the correct vblank timestamp
- * even in VRR mode, as scanout is past the front-porch atm.
- */
- drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
-
- /* Wake up userspace by sending the pageflip event with proper
- * count and timestamp of vblank of flip completion.
- */
- if (e) {
- drm_crtc_send_vblank_event(&amdgpu_crtc->base, e);
-
- /* Event sent, so done with vblank for this flip */
- drm_crtc_vblank_put(&amdgpu_crtc->base);
- }
- } else if (e) {
- /* VRR active and inside front-porch: vblank count and
- * timestamp for pageflip event will only be up to date after
- * drm_crtc_handle_vblank() has been executed from late vblank
- * irq handler after start of back-porch (vline 0). We queue the
- * pageflip event for send-out by drm_crtc_handle_vblank() with
- * updated timestamp and count, once it runs after us.
- *
- * We need to open-code this instead of using the helper
- * drm_crtc_arm_vblank_event(), as that helper would
- * call drm_crtc_accurate_vblank_count(), which we must
- * not call in VRR mode while we are in front-porch!
- */
-
- /* sequence will be replaced by real count during send-out. */
- e->sequence = drm_crtc_vblank_count(&amdgpu_crtc->base);
- e->pipe = amdgpu_crtc->crtc_id;
-
- list_add_tail(&e->base.link, &adev_to_drm(adev)->vblank_event_list);
- e = NULL;
- }
-
- /* Keep track of vblank of this flip for flip throttling. We use the
- * cooked hw counter, as that one incremented at start of this vblank
- * of pageflip completion, so last_flip_vblank is the forbidden count
- * for queueing new pageflips if vsync + VRR is enabled.
- */
- amdgpu_crtc->dm_irq_params.last_flip_vblank =
- amdgpu_get_vblank_counter_kms(&amdgpu_crtc->base);
-
- amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
- spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-
- drm_dbg_state(dev,
- "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n",
- amdgpu_crtc->crtc_id, amdgpu_crtc, vrr_active, (int)!e);
- }
-
- static void dm_handle_vmin_vmax_update(struct work_struct *offload_work)
- {
- struct vupdate_offload_work *work = container_of(offload_work, struct vupdate_offload_work, work);
- struct amdgpu_device *adev = work->adev;
- struct dc_stream_state *stream = work->stream;
- struct dc_crtc_timing_adjust *adjust = work->adjust;
-
- mutex_lock(&adev->dm.dc_lock);
- dc_stream_adjust_vmin_vmax(adev->dm.dc, stream, adjust);
- mutex_unlock(&adev->dm.dc_lock);
-
- dc_stream_release(stream);
- kfree(work->adjust);
- kfree(work);
- }
-
- static void schedule_dc_vmin_vmax(struct amdgpu_device *adev,
- struct dc_stream_state *stream,
- struct dc_crtc_timing_adjust *adjust)
- {
- struct vupdate_offload_work *offload_work = kzalloc_obj(*offload_work,
- GFP_NOWAIT);
- if (!offload_work) {
- drm_dbg_driver(adev_to_drm(adev), "Failed to allocate vupdate_offload_work\n");
- return;
- }
-
- struct dc_crtc_timing_adjust *adjust_copy = kzalloc_obj(*adjust_copy,
- GFP_NOWAIT);
- if (!adjust_copy) {
- drm_dbg_driver(adev_to_drm(adev), "Failed to allocate adjust_copy\n");
- kfree(offload_work);
- return;
- }
-
- dc_stream_retain(stream);
- memcpy(adjust_copy, adjust, sizeof(*adjust_copy));
-
- INIT_WORK(&offload_work->work, dm_handle_vmin_vmax_update);
- offload_work->adev = adev;
- offload_work->stream = stream;
- offload_work->adjust = adjust_copy;
-
- queue_work(system_percpu_wq, &offload_work->work);
- }
-
- /**
- * dm_crtc_high_irq_handler() - Common OTG vblank/flip event handling
- * @adev: amdgpu device
- * @acrtc: the CRTC to service
- *
- * Performs writeback completion, vblank event handling, CRC processing, VRR BTR
- * updates and pageflip completion delivery.
- *
- * On DCN this is driven by VUPDATE_NO_LOCK (the register latch point) from
- * dm_vupdate_high_irq(); on DCE it is driven by VLINE0 at the start of vblank
- * from dm_crtc_high_irq().
- */
- static void dm_crtc_high_irq_handler(struct amdgpu_device *adev,
- struct amdgpu_crtc *acrtc)
- {
- struct drm_writeback_job *job;
- unsigned long flags;
- int vrr_active;
- bool is_dcn = amdgpu_ip_version(adev, DCE_HWIP, 0) != 0;
-
- if (acrtc->wb_conn) {
- spin_lock_irqsave(&acrtc->wb_conn->job_lock, flags);
-
- if (acrtc->wb_pending) {
- job = list_first_entry_or_null(&acrtc->wb_conn->job_queue,
- struct drm_writeback_job,
- list_entry);
- acrtc->wb_pending = false;
- spin_unlock_irqrestore(&acrtc->wb_conn->job_lock, flags);
-
- if (job) {
- unsigned int v_total, refresh_hz;
- struct dc_stream_state *stream = acrtc->dm_irq_params.stream;
-
- v_total = stream->adjust.v_total_max ?
- stream->adjust.v_total_max : stream->timing.v_total;
- refresh_hz = div_u64((uint64_t) stream->timing.pix_clk_100hz *
- 100LL, (v_total * stream->timing.h_total));
- mdelay(1000 / refresh_hz);
-
- drm_writeback_signal_completion(acrtc->wb_conn, 0);
- dc_stream_fc_disable_writeback(adev->dm.dc,
- acrtc->dm_irq_params.stream, 0);
- }
- } else
- spin_unlock_irqrestore(&acrtc->wb_conn->job_lock, flags);
- }
-
- vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
-
- drm_dbg_vbl(adev_to_drm(adev),
- "crtc:%d, vupdate-vrr:%d, planes:%d\n", acrtc->crtc_id,
- vrr_active, acrtc->dm_irq_params.active_planes);
-
- /**
- * Core vblank handling.
- *
- * On DCN this handler runs at VUPDATE_NO_LOCK, the register latch
- * point, which is the correct place to timestamp both VRR and non-VRR
- * vblanks.
- *
- * On DCE this handler runs at the start of front-porch, where only
- * non-VRR timestamping is valid; VRR vblank is deferred to
- * dm_vupdate_high_irq() after end of front-porch.
- */
- if (is_dcn || !vrr_active)
- amdgpu_dm_crtc_handle_vblank(acrtc);
-
- /**
- * Following stuff must happen at start of vblank, for crc
- * computation and below-the-range btr support in vrr mode.
- */
- amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
-
- /* BTR updates need to happen before VUPDATE on Vega and above. */
- if (adev->family < AMDGPU_FAMILY_AI)
- return;
-
- spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-
- if (acrtc->dm_irq_params.stream &&
- acrtc->dm_irq_params.vrr_params.supported) {
- bool replay_en = acrtc->dm_irq_params.stream->link->replay_settings.replay_feature_enabled;
- bool psr_en = acrtc->dm_irq_params.stream->link->psr_settings.psr_feature_enabled;
- bool fs_active_var_en = acrtc->dm_irq_params.freesync_config.state == VRR_STATE_ACTIVE_VARIABLE;
-
- mod_freesync_handle_v_update(adev->dm.freesync_module,
- acrtc->dm_irq_params.stream,
- &acrtc->dm_irq_params.vrr_params);
-
- /* update vmin_vmax only if freesync is enabled, or only if PSR and REPLAY are disabled */
- if (fs_active_var_en || (!fs_active_var_en && !replay_en && !psr_en)) {
- schedule_dc_vmin_vmax(adev, acrtc->dm_irq_params.stream,
- &acrtc->dm_irq_params.vrr_params.adjust);
- }
- }
-
- /*
- * Deliver pageflip completion events (DCN only).
- *
- * Since GRPH_PFLIP is not used, VUPDATE_NO_LOCK is the flip latch
- * point. Deliver any pending pageflip completion event from here,
- * once HW has consumed the new address (the OTG no longer reports a
- * pending flip).
- *
- * Also handle the case here where there aren't any active planes and
- * DCN HUBP may be clock-gated, so the flip-pending status may be
- * undefined.
- */
- if (is_dcn && acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED &&
- acrtc->event) {
-
- if (!dc_get_flip_pending_on_otg(adev->dm.dc, acrtc->otg_inst)) {
- drm_crtc_send_vblank_event(&acrtc->base, acrtc->event);
- acrtc->event = NULL;
- drm_crtc_vblank_put(&acrtc->base);
- acrtc->pflip_status = AMDGPU_FLIP_NONE;
- }
- /*
- * If the flip is still pending, leave it armed and
- * retry on the next vupdate.
- */
- } else if (is_dcn && acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED &&
- acrtc->dm_irq_params.active_planes == 0) {
-
- if (acrtc->event) {
- drm_crtc_send_vblank_event(&acrtc->base, acrtc->event);
- acrtc->event = NULL;
- drm_crtc_vblank_put(&acrtc->base);
- }
- acrtc->pflip_status = AMDGPU_FLIP_NONE;
- }
-
- spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
- }
-
- static void dm_vupdate_high_irq(void *interrupt_params)
- {
- struct common_irq_params *irq_params = interrupt_params;
- struct amdgpu_device *adev = irq_params->adev;
- struct amdgpu_crtc *acrtc;
- struct drm_device *drm_dev;
- struct drm_vblank_crtc *vblank;
- ktime_t frame_duration_ns, previous_timestamp;
- unsigned long flags;
- int vrr_active;
-
- acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
- if (!acrtc)
- return;
-
- vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
- drm_dev = acrtc->base.dev;
- vblank = drm_crtc_vblank_crtc(&acrtc->base);
- previous_timestamp = atomic64_read(&irq_params->previous_timestamp);
- frame_duration_ns = vblank->time - previous_timestamp;
-
- if (frame_duration_ns > 0) {
- trace_amdgpu_refresh_rate_track(acrtc->base.index,
- frame_duration_ns,
- ktime_divns(NSEC_PER_SEC, frame_duration_ns));
- atomic64_set(&irq_params->previous_timestamp, vblank->time);
- }
-
- drm_dbg_vbl(drm_dev,
- "crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id,
- vrr_active);
-
- /*
- * On DCN, VUPDATE_NO_LOCK is the single OTG interrupt used to deliver
- * vblank and pageflip completion events; VSTARTUP and GRPH_PFLIP are
- * not used. Run the full handler here.
- */
- if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0) {
- dm_crtc_high_irq_handler(adev, acrtc);
- return;
- }
-
- /* DCE only below. */
-
- /* Core vblank handling is done here after end of front-porch in
- * vrr mode, as vblank timestamping will give valid results
- * while now done after front-porch. This will also deliver
- * page-flip completion events that have been queued to us
- * if a pageflip happened inside front-porch.
- */
- if (vrr_active && acrtc->dm_irq_params.stream) {
- bool replay_en = acrtc->dm_irq_params.stream->link->replay_settings.replay_feature_enabled;
- bool psr_en = acrtc->dm_irq_params.stream->link->psr_settings.psr_feature_enabled;
- bool fs_active_var_en = acrtc->dm_irq_params.freesync_config.state
- == VRR_STATE_ACTIVE_VARIABLE;
-
- amdgpu_dm_crtc_handle_vblank(acrtc);
-
- /* BTR processing for pre-DCE12 ASICs */
- if (adev->family < AMDGPU_FAMILY_AI) {
- spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
- mod_freesync_handle_v_update(
- adev->dm.freesync_module,
- acrtc->dm_irq_params.stream,
- &acrtc->dm_irq_params.vrr_params);
-
- if (fs_active_var_en || (!fs_active_var_en && !replay_en && !psr_en)) {
- schedule_dc_vmin_vmax(adev,
- acrtc->dm_irq_params.stream,
- &acrtc->dm_irq_params.vrr_params.adjust);
- }
- spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
- }
- }
- }
-
- /**
- * dm_crtc_high_irq() - Handles CRTC interrupt
- * @interrupt_params: used for determining the CRTC instance
- *
- * Handles the CRTC/VSYNC interrupt by notifying DRM's VBLANK event handler.
- *
- * Used on DCE (VLINE0, set to vblank start). On DCN the equivalent handling is
- * driven by VUPDATE_NO_LOCK in dm_vupdate_high_irq().
- */
- static void dm_crtc_high_irq(void *interrupt_params)
- {
- struct common_irq_params *irq_params = interrupt_params;
- struct amdgpu_device *adev = irq_params->adev;
- struct amdgpu_crtc *acrtc;
-
- acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
- if (!acrtc)
- return;
-
- dm_crtc_high_irq_handler(adev, acrtc);
- }
-
- #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- /**
- * dm_dcn_vertical_interrupt0_high_irq() - Handles OTG Vertical interrupt0 for
- * DCN generation ASICs
- * @interrupt_params: interrupt parameters
- *
- * Used to set crc window/read out crc value at vertical line 0 position
- */
- static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
- {
- struct common_irq_params *irq_params = interrupt_params;
- struct amdgpu_device *adev = irq_params->adev;
- struct amdgpu_crtc *acrtc;
-
- acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VLINE0);
-
- if (!acrtc)
- return;
-
- amdgpu_dm_crtc_handle_crc_window_irq(&acrtc->base);
- }
- #endif /* CONFIG_DRM_AMD_SECURE_DISPLAY */
-
- /**
- * dmub_aux_setconfig_callback - Callback for AUX or SET_CONFIG command.
- * @adev: amdgpu_device pointer
- * @notify: dmub notification structure
- *
- * Dmub AUX or SET_CONFIG command completion processing callback
- * Copies dmub notification to DM which is to be read by AUX command.
- * issuing thread and also signals the event to wake up the thread.
- */
- static void dmub_aux_setconfig_callback(struct amdgpu_device *adev,
- struct dmub_notification *notify)
- {
- if (adev->dm.dmub_notify)
- memcpy(adev->dm.dmub_notify, notify, sizeof(struct dmub_notification));
- if (notify->type == DMUB_NOTIFICATION_AUX_REPLY)
- complete(&adev->dm.dmub_aux_transfer_done);
- }
-
- static void dmub_aux_fused_io_callback(struct amdgpu_device *adev,
- struct dmub_notification *notify)
- {
- if (!adev || !notify) {
- ASSERT(false);
- return;
- }
-
- const struct dmub_cmd_fused_request *req = ¬ify->fused_request;
- const uint8_t ddc_line = req->u.aux.ddc_line;
-
- if (ddc_line >= ARRAY_SIZE(adev->dm.fused_io)) {
- ASSERT(false);
- return;
- }
-
- struct fused_io_sync *sync = &adev->dm.fused_io[ddc_line];
-
- static_assert(sizeof(*req) <= sizeof(sync->reply_data), "Size mismatch");
- memcpy(sync->reply_data, req, sizeof(*req));
- complete(&sync->replied);
- }
-
- /**
- * dmub_hpd_callback - DMUB HPD interrupt processing callback.
- * @adev: amdgpu_device pointer
- * @notify: dmub notification structure
- *
- * Dmub Hpd interrupt processing callback. Gets displayindex through the
- * ink index and calls helper to do the processing.
- */
- static void dmub_hpd_callback(struct amdgpu_device *adev,
- struct dmub_notification *notify)
- {
- struct amdgpu_dm_connector *aconnector;
- struct amdgpu_dm_connector *hpd_aconnector = NULL;
- struct drm_connector *connector;
- struct drm_connector_list_iter iter;
- struct dc_link *link;
- u8 link_index = 0;
- struct drm_device *dev;
-
- if (adev == NULL)
- return;
-
- if (notify == NULL) {
- drm_err(adev_to_drm(adev), "DMUB HPD callback notification was NULL");
- return;
- }
-
- if (notify->link_index > adev->dm.dc->link_count) {
- drm_err(adev_to_drm(adev), "DMUB HPD index (%u)is abnormal", notify->link_index);
- return;
- }
-
- /* Skip DMUB HPD IRQ in suspend/resume. We will probe them later. */
- if (notify->type == DMUB_NOTIFICATION_HPD && adev->in_suspend) {
- drm_info(adev_to_drm(adev), "Skip DMUB HPD IRQ callback in suspend/resume\n");
- return;
- }
-
- link_index = notify->link_index;
- link = adev->dm.dc->links[link_index];
- dev = adev->dm.ddev;
-
- drm_connector_list_iter_begin(dev, &iter);
- drm_for_each_connector_iter(connector, &iter) {
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- continue;
-
- aconnector = to_amdgpu_dm_connector(connector);
- if (link && aconnector->dc_link == link) {
- if (notify->type == DMUB_NOTIFICATION_HPD)
- drm_info(adev_to_drm(adev), "DMUB HPD IRQ callback: link_index=%u\n", link_index);
- else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
- drm_info(adev_to_drm(adev), "DMUB HPD RX IRQ callback: link_index=%u\n", link_index);
- else
- drm_warn(adev_to_drm(adev), "DMUB Unknown HPD callback type %d, link_index=%u\n",
- notify->type, link_index);
-
- hpd_aconnector = aconnector;
- break;
- }
- }
- drm_connector_list_iter_end(&iter);
-
- if (hpd_aconnector) {
- if (notify->type == DMUB_NOTIFICATION_HPD) {
- if (hpd_aconnector->dc_link->hpd_status == (notify->hpd_status == DP_HPD_PLUG))
- drm_warn(adev_to_drm(adev), "DMUB reported hpd status unchanged. link_index=%u\n", link_index);
- handle_hpd_irq_helper(hpd_aconnector);
- } else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ) {
- handle_hpd_rx_irq(hpd_aconnector);
- }
- }
- }
-
- /**
- * dmub_hpd_sense_callback - DMUB HPD sense processing callback.
- * @adev: amdgpu_device pointer
- * @notify: dmub notification structure
- *
- * HPD sense changes can occur during low power states and need to be
- * notified from firmware to driver.
- */
- static void dmub_hpd_sense_callback(struct amdgpu_device *adev,
- struct dmub_notification *notify)
- {
- drm_dbg_driver(adev_to_drm(adev), "DMUB HPD SENSE callback.\n");
- }
-
- /**
- * register_dmub_notify_callback - Sets callback for DMUB notify
- * @adev: amdgpu_device pointer
- * @type: Type of dmub notification
- * @callback: Dmub interrupt callback function
- * @dmub_int_thread_offload: offload indicator
- *
- * API to register a dmub callback handler for a dmub notification
- * Also sets indicator whether callback processing to be offloaded.
- * to dmub interrupt handling thread
- * Return: true if successfully registered, false if there is existing registration
- */
- static bool register_dmub_notify_callback(struct amdgpu_device *adev,
- enum dmub_notification_type type,
- dmub_notify_interrupt_callback_t callback,
- bool dmub_int_thread_offload)
- {
- if (callback != NULL && type < ARRAY_SIZE(adev->dm.dmub_thread_offload)) {
- adev->dm.dmub_callback[type] = callback;
- adev->dm.dmub_thread_offload[type] = dmub_int_thread_offload;
- } else
- return false;
-
- return true;
- }
-
- static void dm_handle_hpd_work(struct work_struct *work)
- {
- struct dmub_hpd_work *dmub_hpd_wrk;
-
- dmub_hpd_wrk = container_of(work, struct dmub_hpd_work, handle_hpd_work);
-
- if (!dmub_hpd_wrk->dmub_notify) {
- drm_err(adev_to_drm(dmub_hpd_wrk->adev), "dmub_hpd_wrk dmub_notify is NULL");
- return;
- }
-
- if (dmub_hpd_wrk->dmub_notify->type < ARRAY_SIZE(dmub_hpd_wrk->adev->dm.dmub_callback)) {
- dmub_hpd_wrk->adev->dm.dmub_callback[dmub_hpd_wrk->dmub_notify->type](dmub_hpd_wrk->adev,
- dmub_hpd_wrk->dmub_notify);
- }
-
- kfree(dmub_hpd_wrk->dmub_notify);
- kfree(dmub_hpd_wrk);
-
- }
-
- static const char *dmub_notification_type_str(enum dmub_notification_type e)
- {
- switch (e) {
- case DMUB_NOTIFICATION_NO_DATA:
- return "NO_DATA";
- case DMUB_NOTIFICATION_AUX_REPLY:
- return "AUX_REPLY";
- case DMUB_NOTIFICATION_HPD:
- return "HPD";
- case DMUB_NOTIFICATION_HPD_IRQ:
- return "HPD_IRQ";
- case DMUB_NOTIFICATION_SET_CONFIG_REPLY:
- return "SET_CONFIG_REPLY";
- case DMUB_NOTIFICATION_DPIA_NOTIFICATION:
- return "DPIA_NOTIFICATION";
- case DMUB_NOTIFICATION_HPD_SENSE_NOTIFY:
- return "HPD_SENSE_NOTIFY";
- case DMUB_NOTIFICATION_FUSED_IO:
- return "FUSED_IO";
- default:
- return "<unknown>";
- }
- }
-
- #define DMUB_TRACE_MAX_READ 64
- /**
- * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt
- * @interrupt_params: used for determining the Outbox instance
- *
- * Handles the Outbox Interrupt
- * event handler.
- */
- static void dm_dmub_outbox1_low_irq(void *interrupt_params)
- {
- struct dmub_notification notify = {0};
- struct common_irq_params *irq_params = interrupt_params;
- struct amdgpu_device *adev = irq_params->adev;
- struct amdgpu_display_manager *dm = &adev->dm;
- struct dmcub_trace_buf_entry entry = { 0 };
- u32 count = 0;
- struct dmub_hpd_work *dmub_hpd_wrk;
-
- do {
- if (dc_dmub_srv_get_dmub_outbox0_msg(dm->dc, &entry)) {
- trace_amdgpu_dmub_trace_high_irq(entry.trace_code, entry.tick_count,
- entry.param0, entry.param1);
-
- drm_dbg_driver(adev_to_drm(adev), "trace_code:%u, tick_count:%u, param0:%u, param1:%u\n",
- entry.trace_code, entry.tick_count, entry.param0, entry.param1);
- } else
- break;
-
- count++;
-
- } while (count <= DMUB_TRACE_MAX_READ);
-
- if (count > DMUB_TRACE_MAX_READ)
- drm_dbg_driver(adev_to_drm(adev), "Warning : count > DMUB_TRACE_MAX_READ");
-
- if (dc_enable_dmub_notifications(adev->dm.dc) &&
- irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
-
- do {
- dc_stat_get_dmub_notification(adev->dm.dc, ¬ify);
- if (notify.type >= ARRAY_SIZE(dm->dmub_thread_offload)) {
- drm_err(adev_to_drm(adev), "DM: notify type %d invalid!", notify.type);
- continue;
- }
- if (!dm->dmub_callback[notify.type]) {
- drm_warn(adev_to_drm(adev), "DMUB notification skipped due to no handler: type=%s\n",
- dmub_notification_type_str(notify.type));
- continue;
- }
- if (dm->dmub_thread_offload[notify.type] == true) {
- dmub_hpd_wrk = kzalloc_obj(*dmub_hpd_wrk,
- GFP_ATOMIC);
- if (!dmub_hpd_wrk) {
- drm_err(adev_to_drm(adev), "Failed to allocate dmub_hpd_wrk");
- return;
- }
- dmub_hpd_wrk->dmub_notify = kmemdup(¬ify, sizeof(struct dmub_notification),
- GFP_ATOMIC);
- if (!dmub_hpd_wrk->dmub_notify) {
- kfree(dmub_hpd_wrk);
- drm_err(adev_to_drm(adev), "Failed to allocate dmub_hpd_wrk->dmub_notify");
- return;
- }
- INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
- dmub_hpd_wrk->adev = adev;
- queue_work(adev->dm.delayed_hpd_wq, &dmub_hpd_wrk->handle_hpd_work);
- } else {
- dm->dmub_callback[notify.type](adev, ¬ify);
- }
- } while (notify.pending_notification);
- }
- }
-
static int dm_set_clockgating_state(struct amdgpu_ip_block *ip_block,
enum amd_clockgating_state state)
{
@@@ -1127,401 -327,6 +327,6 @@@ static int dm_set_powergating_state(str
static int dm_early_init(struct amdgpu_ip_block *ip_block);
/* Allocate memory for FBC compressed data */
- static void amdgpu_dm_fbc_init(struct drm_connector *connector)
- {
- struct amdgpu_device *adev = drm_to_adev(connector->dev);
- struct dm_compressor_info *compressor = &adev->dm.compressor;
- struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector);
- struct drm_display_mode *mode;
- unsigned long max_size = 0;
-
- if (adev->dm.dc->fbc_compressor == NULL)
- return;
-
- if (aconn->dc_link->connector_signal != SIGNAL_TYPE_EDP)
- return;
-
- if (compressor->bo_ptr)
- return;
-
-
- list_for_each_entry(mode, &connector->modes, head) {
- if (max_size < (unsigned long) mode->htotal * mode->vtotal)
- max_size = (unsigned long) mode->htotal * mode->vtotal;
- }
-
- if (max_size) {
- int r = amdgpu_bo_create_kernel(adev, max_size * 4, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_GTT, &compressor->bo_ptr,
- &compressor->gpu_addr, &compressor->cpu_addr);
-
- if (r)
- drm_err(adev_to_drm(adev), "DM: Failed to initialize FBC\n");
- else {
- adev->dm.dc->ctx->fbc_gpu_addr = compressor->gpu_addr;
- drm_info(adev_to_drm(adev), "DM: FBC alloc %lu\n", max_size*4);
- }
-
- }
-
- }
-
- static int amdgpu_dm_audio_component_get_eld(struct device *kdev, int port,
- int pipe, bool *enabled,
- unsigned char *buf, int max_bytes)
- {
- struct drm_device *dev = dev_get_drvdata(kdev);
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct drm_connector *connector;
- struct drm_connector_list_iter conn_iter;
- struct amdgpu_dm_connector *aconnector;
- int ret = 0;
-
- *enabled = false;
-
- mutex_lock(&adev->dm.audio_lock);
-
- drm_connector_list_iter_begin(dev, &conn_iter);
- drm_for_each_connector_iter(connector, &conn_iter) {
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- continue;
-
- aconnector = to_amdgpu_dm_connector(connector);
- if (aconnector->audio_inst != port)
- continue;
-
- *enabled = true;
- mutex_lock(&connector->eld_mutex);
- ret = drm_eld_size(connector->eld);
- memcpy(buf, connector->eld, min(max_bytes, ret));
- mutex_unlock(&connector->eld_mutex);
-
- break;
- }
- drm_connector_list_iter_end(&conn_iter);
-
- mutex_unlock(&adev->dm.audio_lock);
-
- drm_dbg_kms(adev_to_drm(adev), "Get ELD : idx=%d ret=%d en=%d\n", port, ret, *enabled);
-
- return ret;
- }
-
- static const struct drm_audio_component_ops amdgpu_dm_audio_component_ops = {
- .get_eld = amdgpu_dm_audio_component_get_eld,
- };
-
- static int amdgpu_dm_audio_component_bind(struct device *kdev,
- struct device *hda_kdev, void *data)
- {
- struct drm_device *dev = dev_get_drvdata(kdev);
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct drm_audio_component *acomp = data;
-
- acomp->ops = &amdgpu_dm_audio_component_ops;
- acomp->dev = kdev;
- adev->dm.audio_component = acomp;
-
- return 0;
- }
-
- static void amdgpu_dm_audio_component_unbind(struct device *kdev,
- struct device *hda_kdev, void *data)
- {
- struct amdgpu_device *adev = drm_to_adev(dev_get_drvdata(kdev));
- struct drm_audio_component *acomp = data;
-
- acomp->ops = NULL;
- acomp->dev = NULL;
- adev->dm.audio_component = NULL;
- }
-
- static const struct component_ops amdgpu_dm_audio_component_bind_ops = {
- .bind = amdgpu_dm_audio_component_bind,
- .unbind = amdgpu_dm_audio_component_unbind,
- };
-
- static int amdgpu_dm_audio_init(struct amdgpu_device *adev)
- {
- int i, ret;
-
- if (!amdgpu_audio)
- return 0;
-
- adev->mode_info.audio.enabled = true;
-
- adev->mode_info.audio.num_pins = adev->dm.dc->res_pool->audio_count;
-
- for (i = 0; i < adev->mode_info.audio.num_pins; i++) {
- adev->mode_info.audio.pin[i].channels = -1;
- adev->mode_info.audio.pin[i].rate = -1;
- adev->mode_info.audio.pin[i].bits_per_sample = -1;
- adev->mode_info.audio.pin[i].status_bits = 0;
- adev->mode_info.audio.pin[i].category_code = 0;
- adev->mode_info.audio.pin[i].connected = false;
- adev->mode_info.audio.pin[i].id =
- adev->dm.dc->res_pool->audios[i]->inst;
- adev->mode_info.audio.pin[i].offset = 0;
- }
-
- ret = component_add(adev->dev, &amdgpu_dm_audio_component_bind_ops);
- if (ret < 0)
- return ret;
-
- adev->dm.audio_registered = true;
-
- return 0;
- }
-
- static void amdgpu_dm_audio_fini(struct amdgpu_device *adev)
- {
- if (!amdgpu_audio)
- return;
-
- if (!adev->mode_info.audio.enabled)
- return;
-
- if (adev->dm.audio_registered) {
- component_del(adev->dev, &amdgpu_dm_audio_component_bind_ops);
- adev->dm.audio_registered = false;
- }
-
- /* TODO: Disable audio? */
-
- adev->mode_info.audio.enabled = false;
- }
-
- static void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin)
- {
- struct drm_audio_component *acomp = adev->dm.audio_component;
-
- if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
- drm_dbg_kms(adev_to_drm(adev), "Notify ELD: %d\n", pin);
-
- acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
- pin, -1);
- }
- }
-
- static int dm_dmub_hw_init(struct amdgpu_device *adev)
- {
- const struct dmcub_firmware_header_v1_0 *hdr;
- struct dmub_srv *dmub_srv = adev->dm.dmub_srv;
- struct dmub_srv_fb_info *fb_info = adev->dm.dmub_fb_info;
- const struct firmware *dmub_fw = adev->dm.dmub_fw;
- struct dc *dc = adev->dm.dc;
- struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
- struct abm *abm = adev->dm.dc->res_pool->abm;
- struct dc_context *ctx = adev->dm.dc->ctx;
- struct dmub_srv_hw_params hw_params;
- enum dmub_status status;
- const unsigned char *fw_inst_const, *fw_bss_data;
- u32 i, fw_inst_const_size, fw_bss_data_size;
- bool has_hw_support;
-
- if (!dmub_srv)
- /* DMUB isn't supported on the ASIC. */
- return 0;
-
- if (!fb_info) {
- drm_err(adev_to_drm(adev), "No framebuffer info for DMUB service.\n");
- return -EINVAL;
- }
-
- if (!dmub_fw) {
- /* Firmware required for DMUB support. */
- drm_err(adev_to_drm(adev), "No firmware provided for DMUB.\n");
- return -EINVAL;
- }
-
- /* initialize register offsets for ASICs with runtime initialization available */
- if (dmub_srv->hw_funcs.init_reg_offsets)
- dmub_srv->hw_funcs.init_reg_offsets(dmub_srv, ctx);
-
- status = dmub_srv_has_hw_support(dmub_srv, &has_hw_support);
- if (status != DMUB_STATUS_OK) {
- drm_err(adev_to_drm(adev), "Error checking HW support for DMUB: %d\n", status);
- return -EINVAL;
- }
-
- if (!has_hw_support) {
- drm_info(adev_to_drm(adev), "DMUB unsupported on ASIC\n");
- return 0;
- }
-
- /* Reset DMCUB if it was previously running - before we overwrite its memory. */
- status = dmub_srv_hw_reset(dmub_srv);
- if (status != DMUB_STATUS_OK)
- drm_warn(adev_to_drm(adev), "Error resetting DMUB HW: %d\n", status);
-
- hdr = (const struct dmcub_firmware_header_v1_0 *)dmub_fw->data;
-
- fw_inst_const = dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- PSP_HEADER_BYTES_256;
-
- fw_bss_data = dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- le32_to_cpu(hdr->inst_const_bytes);
-
- /* Copy firmware and bios info into FB memory. */
- fw_inst_const_size = adev->dm.fw_inst_size;
-
- fw_bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
-
- /* if adev->firmware.load_type == AMDGPU_FW_LOAD_PSP,
- * amdgpu_ucode_init_single_fw will load dmub firmware
- * fw_inst_const part to cw0; otherwise, the firmware back door load
- * will be done by dm_dmub_hw_init
- */
- if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
- memcpy(fb_info->fb[DMUB_WINDOW_0_INST_CONST].cpu_addr, fw_inst_const,
- fw_inst_const_size);
- }
-
- if (fw_bss_data_size)
- memcpy(fb_info->fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr,
- fw_bss_data, fw_bss_data_size);
-
- /* Copy firmware bios info into FB memory. */
- memcpy(fb_info->fb[DMUB_WINDOW_3_VBIOS].cpu_addr, adev->bios,
- adev->bios_size);
-
- /* Reset regions that need to be reset. */
- memset(fb_info->fb[DMUB_WINDOW_4_MAILBOX].cpu_addr, 0,
- fb_info->fb[DMUB_WINDOW_4_MAILBOX].size);
-
- memset(fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].cpu_addr, 0,
- fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].size);
-
- memset(fb_info->fb[DMUB_WINDOW_6_FW_STATE].cpu_addr, 0,
- fb_info->fb[DMUB_WINDOW_6_FW_STATE].size);
-
- memset(fb_info->fb[DMUB_WINDOW_SHARED_STATE].cpu_addr, 0,
- fb_info->fb[DMUB_WINDOW_SHARED_STATE].size);
-
- /* Initialize hardware. */
- memset(&hw_params, 0, sizeof(hw_params));
- hw_params.soc_fb_info.fb_base = adev->gmc.fb_start;
- hw_params.soc_fb_info.fb_offset = adev->vm_manager.vram_base_offset;
-
- /* backdoor load firmware and trigger dmub running */
- if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
- hw_params.load_inst_const = true;
-
- if (dmcu)
- hw_params.psp_version = dmcu->psp_version;
-
- for (i = 0; i < fb_info->num_fb; ++i)
- hw_params.fb[i] = &fb_info->fb[i];
-
- /* Enable usb4 dpia in the FW APU */
- if (dc->caps.is_apu &&
- dc->res_pool->usb4_dpia_count != 0 &&
- !dc->debug.dpia_debug.bits.disable_dpia) {
- hw_params.dpia_supported = true;
- hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia;
- hw_params.dpia_hpd_int_enable_supported = false;
- hw_params.enable_non_transparent_setconfig = dc->config.consolidated_dpia_dp_lt;
- hw_params.disable_dpia_bw_allocation = !dc->config.usb4_bw_alloc_support;
- }
-
- switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
- case IP_VERSION(3, 5, 0):
- case IP_VERSION(3, 5, 1):
- case IP_VERSION(3, 6, 0):
- case IP_VERSION(4, 2, 0):
- case IP_VERSION(4, 2, 1):
- hw_params.ips_sequential_ono = adev->external_rev_id > 0x10;
- hw_params.lower_hbr3_phy_ssc = true;
- break;
- default:
- break;
- }
-
- status = dmub_srv_hw_init(dmub_srv, &hw_params);
- if (status != DMUB_STATUS_OK) {
- drm_err(adev_to_drm(adev), "Error initializing DMUB HW: %d\n", status);
- return -EINVAL;
- }
-
- /* Wait for firmware load to finish. */
- status = dmub_srv_wait_for_auto_load(dmub_srv, 100000);
- if (status != DMUB_STATUS_OK)
- drm_warn(adev_to_drm(adev), "Wait for DMUB auto-load failed: %d\n", status);
-
- /* Init DMCU and ABM if available. */
- if (dmcu && abm) {
- dmcu->funcs->dmcu_init(dmcu);
- abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
- }
-
- if (!adev->dm.dc->ctx->dmub_srv)
- adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv);
- if (!adev->dm.dc->ctx->dmub_srv) {
- drm_err(adev_to_drm(adev), "Couldn't allocate DC DMUB server!\n");
- return -ENOMEM;
- }
-
- drm_info(adev_to_drm(adev), "DMUB hardware initialized: version=0x%08X\n",
- adev->dm.dmcub_fw_version);
-
- /* Keeping sanity checks off if
- * DCN31 >= 4.0.59.0
- * DCN314 >= 8.0.16.0
- * Otherwise, turn on sanity checks
- */
- switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
- case IP_VERSION(3, 1, 2):
- case IP_VERSION(3, 1, 3):
- if (adev->dm.dmcub_fw_version &&
- adev->dm.dmcub_fw_version >= DMUB_FW_VERSION(4, 0, 0) &&
- adev->dm.dmcub_fw_version < DMUB_FW_VERSION(4, 0, 59))
- adev->dm.dc->debug.sanity_checks = true;
- break;
- case IP_VERSION(3, 1, 4):
- if (adev->dm.dmcub_fw_version &&
- adev->dm.dmcub_fw_version >= DMUB_FW_VERSION(4, 0, 0) &&
- adev->dm.dmcub_fw_version < DMUB_FW_VERSION(8, 0, 16))
- adev->dm.dc->debug.sanity_checks = true;
- break;
- default:
- break;
- }
-
- return 0;
- }
-
- static void dm_dmub_hw_resume(struct amdgpu_device *adev)
- {
- struct dmub_srv *dmub_srv = adev->dm.dmub_srv;
- enum dmub_status status;
- bool init;
- int r;
-
- if (!dmub_srv) {
- /* DMUB isn't supported on the ASIC. */
- return;
- }
-
- status = dmub_srv_is_hw_init(dmub_srv, &init);
- if (status != DMUB_STATUS_OK)
- drm_warn(adev_to_drm(adev), "DMUB hardware init check failed: %d\n", status);
-
- if (status == DMUB_STATUS_OK && init) {
- /* Wait for firmware load to finish. */
- status = dmub_srv_wait_for_auto_load(dmub_srv, 100000);
- if (status != DMUB_STATUS_OK)
- drm_warn(adev_to_drm(adev), "Wait for DMUB auto-load failed: %d\n", status);
- } else {
- /* Perform the full hardware initialization. */
- r = dm_dmub_hw_init(adev);
- if (r)
- drm_err(adev_to_drm(adev), "DMUB interface failed to initialize: status=%d\n", r);
- }
- }
-
static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
{
u64 pt_base;
@@@ -1599,151 -404,6 +404,6 @@@
}
- static void force_connector_state(
- struct amdgpu_dm_connector *aconnector,
- enum drm_connector_force force_state)
- {
- struct drm_connector *connector = &aconnector->base;
-
- mutex_lock(&connector->dev->mode_config.mutex);
- aconnector->base.force = force_state;
- mutex_unlock(&connector->dev->mode_config.mutex);
-
- mutex_lock(&aconnector->hpd_lock);
- drm_kms_helper_connector_hotplug_event(connector);
- mutex_unlock(&aconnector->hpd_lock);
- }
-
- static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
- {
- struct hpd_rx_irq_offload_work *offload_work;
- struct amdgpu_dm_connector *aconnector;
- struct dc_link *dc_link;
- struct amdgpu_device *adev;
- enum dc_connection_type new_connection_type = dc_connection_none;
- unsigned long flags;
- union test_response test_response;
-
- memset(&test_response, 0, sizeof(test_response));
-
- offload_work = container_of(work, struct hpd_rx_irq_offload_work, work);
- aconnector = offload_work->offload_wq->aconnector;
- adev = offload_work->adev;
-
- if (!aconnector) {
- drm_err(adev_to_drm(adev), "Can't retrieve aconnector in hpd_rx_irq_offload_work");
- goto skip;
- }
-
- dc_link = aconnector->dc_link;
-
- mutex_lock(&aconnector->hpd_lock);
- if (!dc_link_detect_connection_type(dc_link, &new_connection_type))
- drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
- mutex_unlock(&aconnector->hpd_lock);
-
- if (new_connection_type == dc_connection_none)
- goto skip;
-
- if (amdgpu_in_reset(adev))
- goto skip;
-
- if (offload_work->data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
- offload_work->data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
- dm_handle_mst_sideband_msg_ready_event(&aconnector->mst_mgr, DOWN_OR_UP_MSG_RDY_EVENT);
- spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
- offload_work->offload_wq->is_handling_mst_msg_rdy_event = false;
- spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
- goto skip;
- }
-
- mutex_lock(&adev->dm.dc_lock);
- if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
- dc_link_dp_handle_automated_test(dc_link);
-
- if (aconnector->timing_changed) {
- /* force connector disconnect and reconnect */
- force_connector_state(aconnector, DRM_FORCE_OFF);
- msleep(100);
- force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED);
- }
-
- test_response.bits.ACK = 1;
-
- core_link_write_dpcd(
- dc_link,
- DP_TEST_RESPONSE,
- &test_response.raw,
- sizeof(test_response));
- } else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
- dc_link_check_link_loss_status(dc_link, &offload_work->data) &&
- dc_link_dp_allow_hpd_rx_irq(dc_link)) {
- /* offload_work->data is from handle_hpd_rx_irq->
- * schedule_hpd_rx_offload_work.this is defer handle
- * for hpd short pulse. upon here, link status may be
- * changed, need get latest link status from dpcd
- * registers. if link status is good, skip run link
- * training again.
- */
- union hpd_irq_data irq_data;
-
- memset(&irq_data, 0, sizeof(irq_data));
-
- /* before dc_link_dp_handle_link_loss, allow new link lost handle
- * request be added to work queue if link lost at end of dc_link_
- * dp_handle_link_loss
- */
- spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
- offload_work->offload_wq->is_handling_link_loss = false;
- spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
-
- if ((dc_link_dp_read_hpd_rx_irq_data(dc_link, &irq_data) == DC_OK) &&
- dc_link_check_link_loss_status(dc_link, &irq_data))
- dc_link_dp_handle_link_loss(dc_link);
- }
- mutex_unlock(&adev->dm.dc_lock);
-
- skip:
- kfree(offload_work);
-
- }
-
- static struct hpd_rx_irq_offload_work_queue *hpd_rx_irq_create_workqueue(struct amdgpu_device *adev)
- {
- struct dc *dc = adev->dm.dc;
- int max_caps = dc->caps.max_links;
- int i = 0;
- struct hpd_rx_irq_offload_work_queue *hpd_rx_offload_wq = NULL;
-
- hpd_rx_offload_wq = kzalloc_objs(*hpd_rx_offload_wq, max_caps);
-
- if (!hpd_rx_offload_wq)
- return NULL;
-
-
- for (i = 0; i < max_caps; i++) {
- hpd_rx_offload_wq[i].wq =
- create_singlethread_workqueue("amdgpu_dm_hpd_rx_offload_wq");
-
- if (hpd_rx_offload_wq[i].wq == NULL) {
- drm_err(adev_to_drm(adev), "create amdgpu_dm_hpd_rx_offload_wq fail!");
- goto out_err;
- }
-
- spin_lock_init(&hpd_rx_offload_wq[i].offload_lock);
- }
-
- return hpd_rx_offload_wq;
-
- out_err:
- for (i = 0; i < max_caps; i++) {
- if (hpd_rx_offload_wq[i].wq)
- destroy_workqueue(hpd_rx_offload_wq[i].wq);
- }
- kfree(hpd_rx_offload_wq);
- return NULL;
- }
-
struct amdgpu_stutter_quirk {
u16 chip_vendor;
u16 chip_device;
@@@ -1829,119 -489,6 +489,6 @@@ dm_free_gpu_mem
}
- static enum dmub_status
- dm_dmub_send_vbios_gpint_command(struct amdgpu_device *adev,
- enum dmub_gpint_command command_code,
- uint16_t param,
- uint32_t timeout_us)
- {
- union dmub_gpint_data_register reg, test;
- uint32_t i;
-
- /* Assume that VBIOS DMUB is ready to take commands */
-
- reg.bits.status = 1;
- reg.bits.command_code = command_code;
- reg.bits.param = param;
-
- cgs_write_register(adev->dm.cgs_device, 0x34c0 + 0x01f8, reg.all);
-
- for (i = 0; i < timeout_us; ++i) {
- udelay(1);
-
- /* Check if our GPINT got acked */
- reg.bits.status = 0;
- test = (union dmub_gpint_data_register)
- cgs_read_register(adev->dm.cgs_device, 0x34c0 + 0x01f8);
-
- if (test.all == reg.all)
- return DMUB_STATUS_OK;
- }
-
- return DMUB_STATUS_TIMEOUT;
- }
-
- static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev)
- {
- void *bb;
- long long addr;
- unsigned int bb_size;
- int i = 0;
- uint16_t chunk;
- enum dmub_gpint_command send_addrs[] = {
- DMUB_GPINT__SET_BB_ADDR_WORD0,
- DMUB_GPINT__SET_BB_ADDR_WORD1,
- DMUB_GPINT__SET_BB_ADDR_WORD2,
- DMUB_GPINT__SET_BB_ADDR_WORD3,
- };
- enum dmub_status ret;
-
- switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
- case IP_VERSION(4, 0, 1):
- bb_size = sizeof(struct dml2_soc_bb);
- break;
- case IP_VERSION(4, 2, 0):
- case IP_VERSION(4, 2, 1):
- bb_size = sizeof(struct dml2_soc_bb);
- break;
- default:
- return NULL;
- }
-
- bb = dm_allocate_gpu_mem(adev,
- DC_MEM_ALLOC_TYPE_GART,
- bb_size,
- &addr);
- if (!bb)
- return NULL;
-
- for (i = 0; i < 4; i++) {
- /* Extract 16-bit chunk */
- chunk = ((uint64_t) addr >> (i * 16)) & 0xFFFF;
- /* Send the chunk */
- ret = dm_dmub_send_vbios_gpint_command(adev, send_addrs[i], chunk, 30000);
- if (ret != DMUB_STATUS_OK)
- goto free_bb;
- }
-
- /* Now ask DMUB to copy the bb */
- ret = dm_dmub_send_vbios_gpint_command(adev, DMUB_GPINT__BB_COPY, 1, 200000);
- if (ret != DMUB_STATUS_OK)
- goto free_bb;
-
- return bb;
-
- free_bb:
- dm_free_gpu_mem(adev, DC_MEM_ALLOC_TYPE_GART, (void *) bb);
- return NULL;
-
- }
-
- static enum dmub_ips_disable_type dm_get_default_ips_mode(
- struct amdgpu_device *adev)
- {
- enum dmub_ips_disable_type ret = DMUB_IPS_ENABLE;
-
- switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
- case IP_VERSION(3, 5, 0):
- case IP_VERSION(3, 6, 0):
- case IP_VERSION(3, 5, 1):
- ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF;
- break;
- case IP_VERSION(4, 2, 0):
- case IP_VERSION(4, 2, 1):
- ret = DMUB_IPS_ENABLE;
- break;
- default:
- /* ASICs older than DCN35 do not have IPSs */
- if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0))
- ret = DMUB_IPS_DISABLE_ALL;
- break;
- }
-
- return ret;
- }
-
static int amdgpu_dm_init_power_module(struct amdgpu_display_manager *dm)
{
struct mod_power_init_params init_data[MAX_NUM_EDP];
@@@ -2006,40 -553,6 +553,6 @@@
return 0;
}
- static void hdmi_frl_status_polling_work(struct work_struct *work)
- {
- struct amdgpu_display_manager *dm =
- container_of(to_delayed_work(work), struct amdgpu_display_manager,
- hdmi_frl_status_polling_work);
- struct dc *dc = dm->dc;
- struct dc_link *dc_link;
- bool link_update = false;
-
- for (int i = 0; i < MAX_LINKS; i++) {
- dc_link = dc->links[i];
-
- if (!dc_link || !dc_link->local_sink)
- continue;
-
- if (!dc_is_hdmi_signal(dc_link->connector_signal))
- continue;
-
- if (dc_link->connector_signal != SIGNAL_TYPE_HDMI_FRL)
- continue;
-
- link_update = dc_link_frl_poll_status_flag(dc_link);
- if (link_update) {
- mutex_lock(&dm->dc_lock);
- dc_link_detect(dc_link, DETECT_REASON_RETRAIN);
- mutex_unlock(&dm->dc_lock);
- }
- }
-
- queue_delayed_work(dm->hdmi_frl_status_polling_wq,
- &dm->hdmi_frl_status_polling_work,
- msecs_to_jiffies(dm->hdmi_frl_status_polling_delay_ms));
- }
-
static int amdgpu_dm_init(struct amdgpu_device *adev)
{
struct dc_init_data init_data;
@@@ -2266,7 -779,15 +779,15 @@@
dc_hardware_init(adev->dm.dc);
- adev->dm.hpd_rx_offload_wq = hpd_rx_irq_create_workqueue(adev);
+ /* GOP/vBIOS may leave an OPTC enabled for a display present at power-on
+ * but no longer driven (e.g. an external DP unplugged at boot). Such a
+ * dangling pipe keeps DCN out of idle and blocks s0i3. Power it down
+ * here when nothing needs to be preserved.
+ */
+ if (adev->flags & AMD_IS_APU)
+ dc_disable_dangling_timing_generators(adev->dm.dc);
+
+ adev->dm.hpd_rx_offload_wq = amdgpu_dm_hpd_rx_irq_create_workqueue(adev);
if (!adev->dm.hpd_rx_offload_wq) {
drm_err(adev_to_drm(adev), "failed to create hpd rx offload workqueue.\n");
goto error;
@@@ -2319,8 -840,6 +840,6 @@@
create_singlethread_workqueue("hdmi_frl_status_polling_workqueue");
if (!adev->dm.hdmi_frl_status_polling_wq)
drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_workqueue\n");
- adev->dm.hdmi_frl_status_polling_delay_ms = 200;
- INIT_DELAYED_WORK(&adev->dm.hdmi_frl_status_polling_work, hdmi_frl_status_polling_work);
}
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
init_completion(&adev->dm.dmub_aux_transfer_done);
@@@ -2337,8 -856,8 +856,8 @@@
}
amdgpu_dm_outbox_init(adev);
- if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_AUX_REPLY,
- dmub_aux_setconfig_callback, false)) {
+ if (!dm_register_dmub_notify_callback(adev, DMUB_NOTIFICATION_AUX_REPLY,
+ dm_dmub_aux_setconfig_callback, false)) {
drm_err(adev_to_drm(adev), "fail to register dmub aux callback");
goto error;
}
@@@ -2346,16 -865,17 +865,17 @@@
for (size_t i = 0; i < ARRAY_SIZE(adev->dm.fused_io); i++)
init_completion(&adev->dm.fused_io[i].replied);
- if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_FUSED_IO,
- dmub_aux_fused_io_callback, false)) {
+ if (!dm_register_dmub_notify_callback(adev, DMUB_NOTIFICATION_FUSED_IO,
+ dm_dmub_aux_fused_io_callback, false)) {
drm_err(adev_to_drm(adev), "fail to register dmub fused io callback");
goto error;
}
/* Enable outbox notification only after IRQ handlers are registered and DMUB is alive.
* It is expected that DMUB will resend any pending notifications at this point. Note
- * that hpd and hpd_irq handler registration are deferred to register_hpd_handlers() to
- * align legacy interface initialization sequence. Connection status will be proactivly
- * detected once in the amdgpu_dm_initialize_drm_device.
+ * that hpd and hpd_irq handler registration are deferred to
+ * amdgpu_dm_register_hpd_handlers() to align legacy interface initialization
+ * sequence. Connection status will be proactivly detected once in the
+ * amdgpu_dm_initialize_drm_device.
*/
dc_enable_dmub_outbox(adev->dm.dc);
@@@ -2498,14 -1018,11 +1018,11 @@@ static void amdgpu_dm_fini(struct amdgp
adev->dm.hpd_rx_offload_wq = NULL;
}
+ amdgpu_dm_irq_fini(adev);
+
/* DC Destroy TODO: Replace destroy DAL */
if (adev->dm.dc)
dc_destroy(&adev->dm.dc);
- /*
- * TODO: pageflip, vlank interrupt
- *
- * amdgpu_dm_irq_fini(adev);
- */
if (adev->dm.cgs_device) {
amdgpu_cgs_destroy_device(adev->dm.cgs_device);
@@@ -2635,224 -1152,6 +1152,6 @@@ static int load_dmcu_fw(struct amdgpu_d
return 0;
}
- static uint32_t amdgpu_dm_dmub_reg_read(void *ctx, uint32_t address)
- {
- struct amdgpu_device *adev = ctx;
-
- return dm_read_reg(adev->dm.dc->ctx, address);
- }
-
- static void amdgpu_dm_dmub_reg_write(void *ctx, uint32_t address,
- uint32_t value)
- {
- struct amdgpu_device *adev = ctx;
-
- return dm_write_reg(adev->dm.dc->ctx, address, value);
- }
-
- static int dm_dmub_sw_init(struct amdgpu_device *adev)
- {
- struct dmub_srv_create_params create_params;
- struct dmub_srv_fw_meta_info_params fw_meta_info_params;
- struct dmub_srv_region_params region_params;
- struct dmub_srv_region_info region_info;
- struct dmub_srv_memory_params memory_params;
- struct dmub_fw_meta_info fw_info;
- struct dmub_srv_fb_info *fb_info;
- struct dmub_srv *dmub_srv;
- const struct dmcub_firmware_header_v1_0 *hdr;
- enum dmub_asic dmub_asic;
- enum dmub_status status;
- static enum dmub_window_memory_type window_memory_type[DMUB_WINDOW_TOTAL] = {
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_0_INST_CONST
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_1_STACK
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_2_BSS_DATA
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_3_VBIOS
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_4_MAILBOX
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_5_TRACEBUFF
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_6_FW_STATE
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_7_SCRATCH_MEM
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_IB_MEM
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_SHARED_STATE
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_LSDMA_BUFFER
- DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_CURSOR_OFFLOAD
- };
- int r;
-
- switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
- case IP_VERSION(2, 1, 0):
- dmub_asic = DMUB_ASIC_DCN21;
- break;
- case IP_VERSION(3, 0, 0):
- dmub_asic = DMUB_ASIC_DCN30;
- break;
- case IP_VERSION(3, 0, 1):
- dmub_asic = DMUB_ASIC_DCN301;
- break;
- case IP_VERSION(3, 0, 2):
- dmub_asic = DMUB_ASIC_DCN302;
- break;
- case IP_VERSION(3, 0, 3):
- dmub_asic = DMUB_ASIC_DCN303;
- break;
- case IP_VERSION(3, 1, 2):
- case IP_VERSION(3, 1, 3):
- dmub_asic = (adev->external_rev_id == YELLOW_CARP_B0) ? DMUB_ASIC_DCN31B : DMUB_ASIC_DCN31;
- break;
- case IP_VERSION(3, 1, 4):
- dmub_asic = DMUB_ASIC_DCN314;
- break;
- case IP_VERSION(3, 1, 5):
- dmub_asic = DMUB_ASIC_DCN315;
- break;
- case IP_VERSION(3, 1, 6):
- dmub_asic = DMUB_ASIC_DCN316;
- break;
- case IP_VERSION(3, 2, 0):
- dmub_asic = DMUB_ASIC_DCN32;
- break;
- case IP_VERSION(3, 2, 1):
- dmub_asic = DMUB_ASIC_DCN321;
- break;
- case IP_VERSION(3, 5, 0):
- case IP_VERSION(3, 5, 1):
- dmub_asic = DMUB_ASIC_DCN35;
- break;
- case IP_VERSION(3, 6, 0):
- dmub_asic = DMUB_ASIC_DCN36;
- break;
- case IP_VERSION(4, 0, 1):
- dmub_asic = DMUB_ASIC_DCN401;
- break;
- case IP_VERSION(4, 2, 0):
- dmub_asic = DMUB_ASIC_DCN42;
- break;
- case IP_VERSION(4, 2, 1):
- dmub_asic = DMUB_ASIC_DCN42B;
- break;
- default:
- /* ASIC doesn't support DMUB. */
- return 0;
- }
-
- hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data;
- adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
-
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
- adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id =
- AMDGPU_UCODE_ID_DMCUB;
- adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].fw =
- adev->dm.dmub_fw;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(hdr->inst_const_bytes), PAGE_SIZE);
-
- drm_info(adev_to_drm(adev), "Loading DMUB firmware via PSP: version=0x%08X\n",
- adev->dm.dmcub_fw_version);
- }
-
-
- adev->dm.dmub_srv = kzalloc_obj(*adev->dm.dmub_srv);
- dmub_srv = adev->dm.dmub_srv;
-
- if (!dmub_srv) {
- drm_err(adev_to_drm(adev), "Failed to allocate DMUB service!\n");
- return -ENOMEM;
- }
-
- memset(&create_params, 0, sizeof(create_params));
- create_params.user_ctx = adev;
- create_params.funcs.reg_read = amdgpu_dm_dmub_reg_read;
- create_params.funcs.reg_write = amdgpu_dm_dmub_reg_write;
- create_params.asic = dmub_asic;
-
- /* Create the DMUB service. */
- status = dmub_srv_create(dmub_srv, &create_params);
- if (status != DMUB_STATUS_OK) {
- drm_err(adev_to_drm(adev), "Error creating DMUB service: %d\n", status);
- return -EINVAL;
- }
-
- /* Extract the FW meta info. */
- memset(&fw_meta_info_params, 0, sizeof(fw_meta_info_params));
-
- fw_meta_info_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
- PSP_HEADER_BYTES_256;
- fw_meta_info_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
- fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- PSP_HEADER_BYTES_256;
- fw_meta_info_params.fw_bss_data = fw_meta_info_params.bss_data_size ? adev->dm.dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- le32_to_cpu(hdr->inst_const_bytes) : NULL;
- fw_meta_info_params.custom_psp_footer_size = 0;
-
- status = dmub_srv_get_fw_meta_info_from_raw_fw(&fw_meta_info_params, &fw_info);
- if (status != DMUB_STATUS_OK) {
- /* Skip returning early, just log the error. */
- drm_err(adev_to_drm(adev), "Error getting DMUB FW meta info: %d\n", status);
- // return -EINVAL;
- }
-
- /* Calculate the size of all the regions for the DMUB service. */
- memset(®ion_params, 0, sizeof(region_params));
-
- region_params.inst_const_size = fw_meta_info_params.inst_const_size;
- region_params.bss_data_size = fw_meta_info_params.bss_data_size;
- region_params.vbios_size = adev->bios_size;
- region_params.fw_bss_data = fw_meta_info_params.fw_bss_data;
- region_params.fw_inst_const = fw_meta_info_params.fw_inst_const;
- region_params.window_memory_type = window_memory_type;
- region_params.fw_info = (status == DMUB_STATUS_OK) ? &fw_info : NULL;
-
- status = dmub_srv_calc_region_info(dmub_srv, ®ion_params,
- ®ion_info);
-
- if (status != DMUB_STATUS_OK) {
- drm_err(adev_to_drm(adev), "Error calculating DMUB region info: %d\n", status);
- return -EINVAL;
- }
-
- /*
- * Allocate a framebuffer based on the total size of all the regions.
- * TODO: Move this into GART.
- */
- r = amdgpu_bo_create_kernel(adev, region_info.fb_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM |
- AMDGPU_GEM_DOMAIN_GTT,
- &adev->dm.dmub_bo,
- &adev->dm.dmub_bo_gpu_addr,
- &adev->dm.dmub_bo_cpu_addr);
- if (r)
- return r;
-
- /* Rebase the regions on the framebuffer address. */
- memset(&memory_params, 0, sizeof(memory_params));
- memory_params.cpu_fb_addr = adev->dm.dmub_bo_cpu_addr;
- memory_params.gpu_fb_addr = adev->dm.dmub_bo_gpu_addr;
- memory_params.region_info = ®ion_info;
- memory_params.window_memory_type = window_memory_type;
-
- adev->dm.dmub_fb_info = kzalloc_obj(*adev->dm.dmub_fb_info);
- fb_info = adev->dm.dmub_fb_info;
-
- if (!fb_info) {
- drm_err(adev_to_drm(adev),
- "Failed to allocate framebuffer info for DMUB service!\n");
- return -ENOMEM;
- }
-
- status = dmub_srv_calc_mem_info(dmub_srv, &memory_params, fb_info);
- if (status != DMUB_STATUS_OK) {
- drm_err(adev_to_drm(adev), "Error calculating DMUB FB info: %d\n", status);
- return -EINVAL;
- }
-
- adev->dm.bb_from_dmub = dm_dmub_get_vbios_bounding_box(adev);
- adev->dm.fw_inst_size = fw_meta_info_params.inst_const_size;
-
- return 0;
- }
-
static int dm_sw_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@@ -2906,41 -1205,6 +1205,6 @@@ static int dm_sw_fini(struct amdgpu_ip_
return 0;
}
- static int detect_mst_link_for_all_connectors(struct drm_device *dev)
- {
- struct amdgpu_dm_connector *aconnector;
- struct drm_connector *connector;
- struct drm_connector_list_iter iter;
- int ret = 0;
-
- drm_connector_list_iter_begin(dev, &iter);
- drm_for_each_connector_iter(connector, &iter) {
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- continue;
-
- aconnector = to_amdgpu_dm_connector(connector);
- if (aconnector->dc_link->type == dc_connection_mst_branch &&
- aconnector->mst_mgr.aux) {
- drm_dbg_kms(dev, "DM_MST: starting TM on aconnector: %p [id: %d]\n",
- aconnector,
- aconnector->base.base.id);
-
- ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
- if (ret < 0) {
- drm_err(dev, "DM_MST: Failed to start MST\n");
- aconnector->dc_link->type =
- dc_connection_single;
- ret = dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
- aconnector->dc_link);
- break;
- }
- }
- }
- drm_connector_list_iter_end(&iter);
-
- return ret;
- }
static void amdgpu_dm_boot_time_crc_init(struct amdgpu_device *adev)
{
@@@ -3038,7 -1302,7 +1302,7 @@@ static int dm_late_init(struct amdgpu_i
}
}
- return detect_mst_link_for_all_connectors(adev_to_drm(adev));
+ return amdgpu_dm_detect_mst_link_for_all_connectors(adev_to_drm(adev));
}
static void resume_mst_branch_status(struct drm_dp_mst_topology_mgr *mgr)
@@@ -3092,48 -1356,6 +1356,6 @@@ out_fail
mutex_unlock(&mgr->lock);
}
- void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector)
- {
- struct cec_notifier *n = aconnector->notifier;
-
- if (!n)
- return;
-
- cec_notifier_phys_addr_invalidate(n);
- }
-
- void hdmi_cec_set_edid(struct amdgpu_dm_connector *aconnector)
- {
- struct drm_connector *connector = &aconnector->base;
- struct cec_notifier *n = aconnector->notifier;
-
- if (!n)
- return;
-
- cec_notifier_set_phys_addr(n,
- connector->display_info.source_physical_address);
- }
-
- static void s3_handle_hdmi_cec(struct drm_device *ddev, bool suspend)
- {
- struct amdgpu_dm_connector *aconnector;
- struct drm_connector *connector;
- struct drm_connector_list_iter conn_iter;
-
- drm_connector_list_iter_begin(ddev, &conn_iter);
- drm_for_each_connector_iter(connector, &conn_iter) {
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- continue;
-
- aconnector = to_amdgpu_dm_connector(connector);
- if (suspend)
- hdmi_cec_unset_edid(aconnector);
- else
- hdmi_cec_set_edid(aconnector);
- }
- drm_connector_list_iter_end(&conn_iter);
- }
-
static void s3_handle_mst(struct drm_device *dev, bool suspend)
{
struct amdgpu_dm_connector *aconnector;
@@@ -3236,7 -1458,7 +1458,7 @@@ static int dm_oem_i2c_hw_init(struct am
oem_ddc_service = dc_get_oem_i2c_device(adev->dm.dc);
if (oem_ddc_service) {
- oem_i2c = create_i2c(oem_ddc_service, true);
+ oem_i2c = amdgpu_dm_create_i2c(oem_ddc_service, true);
if (!oem_i2c) {
drm_info(adev_to_drm(adev), "Failed to create oem i2c adapter data\n");
return -ENOMEM;
@@@ -3279,17 -1501,26 +1501,26 @@@ static int dm_hw_init(struct amdgpu_ip_
struct amdgpu_device *adev = ip_block->adev;
int r;
+ adev->dm.i2c_devres_group = devres_open_group(adev->dev, NULL, GFP_KERNEL);
+ if (!adev->dm.i2c_devres_group)
+ return -ENOMEM;
+
/* Create DAL display manager */
r = amdgpu_dm_init(adev);
if (r)
- return r;
+ goto err_release_i2c;
amdgpu_dm_hpd_init(adev);
r = dm_oem_i2c_hw_init(adev);
if (r)
drm_info(adev_to_drm(adev), "Failed to add OEM i2c bus\n");
+ devres_close_group(adev->dev, adev->dm.i2c_devres_group);
return 0;
+
+ err_release_i2c:
+ devres_release_group(adev->dev, adev->dm.i2c_devres_group);
+ return r;
}
/**
@@@ -3304,9 -1535,11 +1535,11 @@@ static int dm_hw_fini(struct amdgpu_ip_
{
struct amdgpu_device *adev = ip_block->adev;
+ if (adev->dm.i2c_devres_group)
+ devres_release_group(adev->dev, adev->dm.i2c_devres_group);
+
amdgpu_dm_hpd_fini(adev);
- amdgpu_dm_irq_fini(adev);
amdgpu_dm_fini(adev);
return 0;
}
@@@ -3321,10 -1554,11 +1554,11 @@@ static void dm_gpureset_toggle_interrup
int i = 0;
for (i = 0; i < state->stream_count; i++) {
- acrtc = get_crtc_by_otg_inst(
+ acrtc = amdgpu_dm_get_crtc_by_otg_inst(
adev, state->stream_status[i].primary_otg_inst);
- if (acrtc && state->stream_status[i].plane_count != 0) {
+ if (acrtc && state->stream_status[i].plane_count != 0 &&
+ amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) {
irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst;
rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
if (rc)
@@@ -3405,16 -1639,6 +1639,6 @@@ static enum dc_status amdgpu_dm_commit_
return dc_commit_streams(dc, ¶ms);
}
- static void hpd_rx_irq_work_suspend(struct amdgpu_display_manager *dm)
- {
- int i;
-
- if (dm->hpd_rx_offload_wq) {
- for (i = 0; i < dm->dc->caps.max_links; i++)
- flush_workqueue(dm->hpd_rx_offload_wq[i].wq);
- }
- }
-
static int dm_cache_state(struct amdgpu_device *adev)
{
int r;
@@@ -3510,7 -1734,7 +1734,7 @@@ static int dm_suspend(struct amdgpu_ip_
amdgpu_dm_irq_suspend(adev);
- hpd_rx_irq_work_suspend(dm);
+ amdgpu_dm_hpd_rx_irq_work_suspend(dm);
return 0;
}
@@@ -3522,7 -1746,7 +1746,7 @@@
return r;
}
- s3_handle_hdmi_cec(adev_to_drm(adev), true);
+ amdgpu_dm_s3_handle_hdmi_cec(adev_to_drm(adev), true);
s3_handle_mst(adev_to_drm(adev), true);
@@@ -3536,7 -1760,7 +1760,7 @@@
scoped_guard(mutex, &dm->dc_lock)
amdgpu_dm_ism_force_full_power(dm);
- hpd_rx_irq_work_suspend(dm);
+ amdgpu_dm_hpd_rx_irq_work_suspend(dm);
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
@@@ -3548,26 -1772,7 +1772,7 @@@
return 0;
}
- struct drm_connector *
- amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_commit *state,
- struct drm_crtc *crtc)
- {
- u32 i;
- struct drm_connector_state *new_con_state;
- struct drm_connector *connector;
- struct drm_crtc *crtc_from_state;
-
- for_each_new_connector_in_state(state, connector, new_con_state, i) {
- crtc_from_state = new_con_state->crtc;
-
- if (crtc_from_state == crtc)
- return connector;
- }
-
- return NULL;
- }
-
- static void emulated_link_detect(struct dc_link *link)
+ void amdgpu_dm_emulated_link_detect(struct dc_link *link)
{
struct dc_sink_init_data sink_init_data = { 0 };
struct display_sink_capability sink_caps = { 0 };
@@@ -3688,8 -1893,8 +1893,8 @@@ static void dm_gpureset_commit_state(st
}
}
- static void apply_delay_after_dpcd_poweroff(struct amdgpu_device *adev,
- struct dc_sink *sink)
+ void amdgpu_dm_apply_delay_after_dpcd_poweroff(struct amdgpu_device *adev,
+ struct dc_sink *sink)
{
struct dc_panel_patch *ppatch = NULL;
@@@ -3832,8 -2037,7 +2037,7 @@@ static int dm_resume(struct amdgpu_ip_b
for (i = 0; i < dc_state->stream_count; i++) {
dc_state->streams[i]->mode_changed = true;
for (j = 0; j < dc_state->stream_status[i].plane_count; j++) {
- dc_state->stream_status[i].plane_states[j]->update_flags.raw
- = 0xffffffff;
+ dc_pipe_update_bits_set_full(&dc_state->stream_status[i].plane_states[j]->update_bits);
}
}
@@@ -3896,7 -2100,7 +2100,7 @@@
*/
amdgpu_dm_irq_resume_early(adev);
- s3_handle_hdmi_cec(ddev, false);
+ amdgpu_dm_s3_handle_hdmi_cec(ddev, false);
/* On resume we need to rewrite the MSTM control bits to enable MST*/
s3_handle_mst(ddev, false);
@@@ -3931,14 -2135,14 +2135,14 @@@
drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
if (aconnector->base.force && new_connection_type == dc_connection_none) {
- emulated_link_detect(aconnector->dc_link);
+ amdgpu_dm_emulated_link_detect(aconnector->dc_link);
} else {
guard(mutex)(&dm->dc_lock);
dc_exit_ips_for_hw_access(dm->dc);
ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_RESUMEFROMS3S4);
if (ret) {
/* w/a delay for certain panels */
- apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink);
+ amdgpu_dm_apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink);
}
}
@@@ -4016,7 -2220,6 +2220,6 @@@ static const struct amd_ip_funcs amdgpu
.resume = dm_resume,
.is_idle = dm_is_idle,
.wait_for_idle = dm_wait_for_idle,
- .check_soft_reset = dm_check_soft_reset,
.soft_reset = dm_soft_reset,
.set_clockgating_state = dm_set_clockgating_state,
.set_powergating_state = dm_set_powergating_state,
@@@ -4049,1004 -2252,6 +2252,6 @@@ static struct drm_mode_config_helper_fu
.atomic_commit_setup = amdgpu_dm_atomic_setup_commit,
};
- #define DDC_MANUFACTURERNAME_SAMSUNG 0x2D4C
-
- static void dm_set_panel_type(struct amdgpu_dm_connector *aconnector)
- {
- struct drm_connector *connector = &aconnector->base;
- struct drm_display_info *display_info = &connector->display_info;
- struct dc_link *link = aconnector->dc_link;
- struct amdgpu_device *adev;
-
- adev = drm_to_adev(connector->dev);
-
- link->panel_type = PANEL_TYPE_NONE;
-
- switch (display_info->amd_vsdb.panel_type) {
- case AMD_VSDB_PANEL_TYPE_OLED:
- link->panel_type = PANEL_TYPE_OLED;
- break;
- case AMD_VSDB_PANEL_TYPE_MINILED:
- link->panel_type = PANEL_TYPE_MINILED;
- break;
- }
-
- /* If VSDB didn't determine panel type, check DPCD ext caps */
- if (link->panel_type == PANEL_TYPE_NONE) {
- if (link->dpcd_sink_ext_caps.bits.miniled == 1)
- link->panel_type = PANEL_TYPE_MINILED;
- if (link->dpcd_sink_ext_caps.bits.oled == 1)
- link->panel_type = PANEL_TYPE_OLED;
- }
-
- /*
- * TODO: get panel type from DID2 that has device technology field
- * to specify if it's OLED or not. But we need to wait for DID2
- * support in DC and EDID parser to be able to use it here.
- */
-
- if (link->panel_type == PANEL_TYPE_NONE) {
- struct drm_amd_vsdb_info *vsdb = &display_info->amd_vsdb;
- u32 lum1_max = vsdb->luminance_range1.max_luminance;
- u32 lum2_max = vsdb->luminance_range2.max_luminance;
-
- if (vsdb->version && link->local_sink &&
- link->local_sink->edid_caps.manufacturer_id ==
- DDC_MANUFACTURERNAME_SAMSUNG &&
- lum1_max >= ((lum2_max * 3) / 2))
- link->panel_type = PANEL_TYPE_MINILED;
- }
-
- if (link->panel_type == PANEL_TYPE_OLED)
- drm_object_property_set_value(&connector->base,
- adev_to_drm(adev)->mode_config.panel_type_property,
- DRM_MODE_PANEL_TYPE_OLED);
- else
- drm_object_property_set_value(&connector->base,
- adev_to_drm(adev)->mode_config.panel_type_property,
- DRM_MODE_PANEL_TYPE_UNKNOWN);
-
- drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n", link->panel_type);
- }
-
- static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
- {
- const struct drm_panel_backlight_quirk *panel_backlight_quirk;
- struct amdgpu_dm_backlight_caps *caps;
- struct drm_connector *conn_base;
- struct amdgpu_device *adev;
- struct drm_luminance_range_info *luminance_range;
- struct drm_device *drm;
-
- if (aconnector->bl_idx == -1 ||
- aconnector->dc_link->connector_signal != SIGNAL_TYPE_EDP)
- return;
-
- conn_base = &aconnector->base;
- drm = conn_base->dev;
- adev = drm_to_adev(drm);
-
- caps = &adev->dm.backlight_caps[aconnector->bl_idx];
- caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
- caps->aux_support = false;
-
- panel_backlight_quirk = drm_get_panel_backlight_quirk(aconnector->drm_edid);
-
- if (caps->ext_caps->bits.oled == 1
- /*
- * ||
- * caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
- * caps->ext_caps->bits.hdr_aux_backlight_control == 1
- */)
- caps->aux_support = true;
-
- if (amdgpu_backlight == 0)
- caps->aux_support = false;
- else if (amdgpu_backlight == 1)
- caps->aux_support = true;
- else if (!IS_ERR_OR_NULL(panel_backlight_quirk) &&
- panel_backlight_quirk->force_pwm)
- caps->aux_support = false;
- if (caps->aux_support)
- aconnector->dc_link->backlight_control_type = BACKLIGHT_CONTROL_AMD_AUX;
-
- luminance_range = &conn_base->display_info.luminance_range;
-
- if (luminance_range->max_luminance)
- caps->aux_max_input_signal = luminance_range->max_luminance;
- else
- caps->aux_max_input_signal = 512;
-
- if (luminance_range->min_luminance)
- caps->aux_min_input_signal = luminance_range->min_luminance;
- else
- caps->aux_min_input_signal = 1;
-
- if (!IS_ERR_OR_NULL(panel_backlight_quirk)) {
- if (panel_backlight_quirk->min_brightness) {
- caps->min_input_signal =
- panel_backlight_quirk->min_brightness - 1;
- drm_info(drm,
- "Applying panel backlight quirk, min_brightness: %d\n",
- caps->min_input_signal);
- }
- if (panel_backlight_quirk->brightness_mask) {
- drm_info(drm,
- "Applying panel backlight quirk, brightness_mask: 0x%X\n",
- panel_backlight_quirk->brightness_mask);
- caps->brightness_mask =
- panel_backlight_quirk->brightness_mask;
- }
- }
- }
-
- DEFINE_FREE(sink_release, struct dc_sink *, if (_T) dc_sink_release(_T))
-
- void amdgpu_dm_update_connector_after_detect(
- struct amdgpu_dm_connector *aconnector)
- {
- struct drm_connector *connector = &aconnector->base;
- struct dc_sink *sink __free(sink_release) = NULL;
- struct drm_device *dev = connector->dev;
-
- /* MST handled by drm_mst framework */
- if (aconnector->mst_mgr.mst_state == true)
- return;
-
- sink = aconnector->dc_link->local_sink;
- if (sink)
- dc_sink_retain(sink);
-
- /*
- * Edid mgmt connector gets first update only in mode_valid hook and then
- * the connector sink is set to either fake or physical sink depends on link status.
- * Skip if already done during boot.
- */
- if (aconnector->base.force != DRM_FORCE_UNSPECIFIED
- && aconnector->dc_em_sink) {
-
- /*
- * For S3 resume with headless use eml_sink to fake stream
- * because on resume connector->sink is set to NULL
- */
- guard(mutex)(&dev->mode_config.mutex);
-
- if (sink) {
- if (aconnector->dc_sink) {
- amdgpu_dm_update_freesync_caps(connector, NULL, true);
- /*
- * retain and release below are used to
- * bump up refcount for sink because the link doesn't point
- * to it anymore after disconnect, so on next crtc to connector
- * reshuffle by UMD we will get into unwanted dc_sink release
- */
- dc_sink_release(aconnector->dc_sink);
- }
- aconnector->dc_sink = sink;
- dc_sink_retain(aconnector->dc_sink);
- amdgpu_dm_update_freesync_caps(connector,
- aconnector->drm_edid, true);
- } else {
- amdgpu_dm_update_freesync_caps(connector, NULL, true);
- if (!aconnector->dc_sink) {
- aconnector->dc_sink = aconnector->dc_em_sink;
- dc_sink_retain(aconnector->dc_sink);
- }
- }
-
- return;
- }
-
- /*
- * TODO: temporary guard to look for proper fix
- * if this sink is MST sink, we should not do anything
- */
- if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
- return;
-
- if (aconnector->dc_sink == sink) {
- /*
- * We got a DP short pulse (Link Loss, DP CTS, etc...).
- * Do nothing!!
- */
- drm_dbg_kms(dev, "DCHPD: connector_id=%d: dc_sink didn't change.\n",
- aconnector->connector_id);
- return;
- }
-
- drm_dbg_kms(dev, "DCHPD: connector_id=%d: Old sink=%p New sink=%p\n",
- aconnector->connector_id, aconnector->dc_sink, sink);
-
- /* When polling, DRM has already locked the mutex for us. */
- if (!drm_kms_helper_is_poll_worker())
- mutex_lock(&dev->mode_config.mutex);
-
- /*
- * 1. Update status of the drm connector
- * 2. Send an event and let userspace tell us what to do
- */
- if (sink) {
- /*
- * TODO: check if we still need the S3 mode update workaround.
- * If yes, put it here.
- */
- if (aconnector->dc_sink) {
- amdgpu_dm_update_freesync_caps(connector, NULL, true);
- dc_sink_release(aconnector->dc_sink);
- }
-
- aconnector->dc_sink = sink;
- dc_sink_retain(aconnector->dc_sink);
- drm_edid_free(aconnector->drm_edid);
- aconnector->drm_edid = NULL;
- if (sink->dc_edid.length == 0) {
- hdmi_cec_unset_edid(aconnector);
- if (aconnector->dc_link->aux_mode) {
- drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
- }
- } else {
- const struct edid *edid = (const struct edid *)sink->dc_edid.raw_edid;
-
- aconnector->drm_edid = drm_edid_alloc(edid, sink->dc_edid.length);
- drm_edid_connector_update(connector, aconnector->drm_edid);
-
- hdmi_cec_set_edid(aconnector);
- if (aconnector->dc_link->aux_mode)
- drm_dp_cec_attach(&aconnector->dm_dp_aux.aux,
- connector->display_info.source_physical_address);
- }
-
- if (!aconnector->timing_requested) {
- aconnector->timing_requested =
- kzalloc_obj(struct dc_crtc_timing);
- if (!aconnector->timing_requested)
- drm_err(dev,
- "failed to create aconnector->requested_timing\n");
- }
-
- amdgpu_dm_update_freesync_caps(connector, aconnector->drm_edid, true);
- update_connector_ext_caps(aconnector);
- dm_set_panel_type(aconnector);
- } else {
- hdmi_cec_unset_edid(aconnector);
- drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
- amdgpu_dm_update_freesync_caps(connector, NULL, true);
- aconnector->num_modes = 0;
- dc_sink_release(aconnector->dc_sink);
- aconnector->dc_sink = NULL;
- drm_edid_free(aconnector->drm_edid);
- aconnector->drm_edid = NULL;
- kfree(aconnector->timing_requested);
- aconnector->timing_requested = NULL;
- /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
- if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
- connector->state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
- }
-
- update_subconnector_property(aconnector);
-
- /* When polling, the mutex will be unlocked for us by DRM. */
- if (!drm_kms_helper_is_poll_worker())
- mutex_unlock(&dev->mode_config.mutex);
- }
-
- static bool are_sinks_equal(const struct dc_sink *sink1, const struct dc_sink *sink2)
- {
- if (!sink1 || !sink2)
- return false;
- if (sink1->sink_signal != sink2->sink_signal)
- return false;
-
- if (sink1->dc_edid.length != sink2->dc_edid.length)
- return false;
-
- if (memcmp(sink1->dc_edid.raw_edid, sink2->dc_edid.raw_edid,
- sink1->dc_edid.length) != 0)
- return false;
- return true;
- }
-
-
- /**
- * DOC: hdmi_hpd_debounce_work
- *
- * HDMI HPD debounce delay in milliseconds. When an HDMI display toggles HPD
- * (such as during power save transitions), this delay determines how long to
- * wait before processing the HPD event. This allows distinguishing between a
- * physical unplug (>hdmi_hpd_debounce_delay)
- * and a spontaneous RX HPD toggle (<hdmi_hpd_debounce_delay).
- *
- * If the toggle is less than this delay, the driver compares sink capabilities
- * and permits a hotplug event if they changed.
- *
- * The default value of 1500ms was chosen based on experimental testing with
- * various monitors that exhibit spontaneous HPD toggling behavior.
- */
- static void hdmi_hpd_debounce_work(struct work_struct *work)
- {
- struct amdgpu_dm_connector *aconnector =
- container_of(to_delayed_work(work), struct amdgpu_dm_connector,
- hdmi_hpd_debounce_work);
- struct drm_connector *connector = &aconnector->base;
- struct drm_device *dev = connector->dev;
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct dc *dc = aconnector->dc_link->ctx->dc;
- bool fake_reconnect = false;
- bool reallow_idle = false;
- bool ret = false;
- guard(mutex)(&aconnector->hpd_lock);
-
- /* Re-detect the display */
- scoped_guard(mutex, &adev->dm.dc_lock) {
- if (dc->caps.ips_support && dc->ctx->dmub_srv->idle_allowed) {
- dc_allow_idle_optimizations(dc, false);
- reallow_idle = true;
- }
- ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
- }
-
- if (ret) {
- /* Apply workaround delay for certain panels */
- apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink);
- /* Compare sinks to determine if this was a spontaneous HPD toggle */
- if (are_sinks_equal(aconnector->dc_link->local_sink, aconnector->hdmi_prev_sink)) {
- /*
- * Sinks match - this was a spontaneous HDMI HPD toggle.
- */
- drm_dbg_kms(dev, "HDMI HPD: Sink unchanged after debounce, internal re-enable\n");
- fake_reconnect = true;
- }
-
- /* Update connector state */
- amdgpu_dm_update_connector_after_detect(aconnector);
-
- drm_modeset_lock_all(dev);
- dm_restore_drm_connector_state(dev, connector);
- drm_modeset_unlock_all(dev);
-
- /* Only notify OS if sink actually changed */
- if (!fake_reconnect && aconnector->base.force == DRM_FORCE_UNSPECIFIED)
- drm_kms_helper_hotplug_event(dev);
- }
-
- /* Release the cached sink reference */
- if (aconnector->hdmi_prev_sink) {
- dc_sink_release(aconnector->hdmi_prev_sink);
- aconnector->hdmi_prev_sink = NULL;
- }
-
- scoped_guard(mutex, &adev->dm.dc_lock) {
- if (reallow_idle && dc->caps.ips_support)
- dc_allow_idle_optimizations(dc, true);
- }
- }
-
- static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
- {
- struct drm_connector *connector = &aconnector->base;
- struct drm_device *dev = connector->dev;
- enum dc_connection_type new_connection_type = dc_connection_none;
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
- struct dc *dc = aconnector->dc_link->ctx->dc;
- bool ret = false;
- bool debounce_required = false;
-
- if (adev->dm.disable_hpd_irq)
- return;
-
- /*
- * In case of failure or MST no need to update connector status or notify the OS
- * since (for MST case) MST does this in its own context.
- */
- guard(mutex)(&aconnector->hpd_lock);
-
- if (adev->dm.hdcp_workqueue) {
- hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index);
- dm_con_state->update_hdcp = true;
- }
- if (aconnector->fake_enable)
- aconnector->fake_enable = false;
-
- aconnector->timing_changed = false;
-
- if (!dc_link_detect_connection_type(aconnector->dc_link, &new_connection_type))
- drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
-
- /*
- * Check for HDMI disconnect with debounce enabled.
- */
- debounce_required = (aconnector->hdmi_hpd_debounce_delay_ms > 0 &&
- dc_is_hdmi_signal(aconnector->dc_link->connector_signal) &&
- new_connection_type == dc_connection_none &&
- aconnector->dc_link->local_sink != NULL);
-
- if (aconnector->base.force && new_connection_type == dc_connection_none) {
- emulated_link_detect(aconnector->dc_link);
-
- drm_modeset_lock_all(dev);
- dm_restore_drm_connector_state(dev, connector);
- drm_modeset_unlock_all(dev);
-
- if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
- drm_kms_helper_connector_hotplug_event(connector);
- } else if (debounce_required) {
- /*
- * HDMI disconnect detected - schedule delayed work instead of
- * processing immediately. This allows us to coalesce spurious
- * HDMI signals from physical unplugs.
- */
- drm_dbg_kms(dev, "HDMI HPD: Disconnect detected, scheduling debounce work (%u ms)\n",
- aconnector->hdmi_hpd_debounce_delay_ms);
-
- /* Cache the current sink for later comparison */
- if (aconnector->hdmi_prev_sink)
- dc_sink_release(aconnector->hdmi_prev_sink);
- aconnector->hdmi_prev_sink = aconnector->dc_link->local_sink;
- if (aconnector->hdmi_prev_sink)
- dc_sink_retain(aconnector->hdmi_prev_sink);
-
- /* Schedule delayed detection. */
- if (mod_delayed_work(system_percpu_wq,
- &aconnector->hdmi_hpd_debounce_work,
- msecs_to_jiffies(aconnector->hdmi_hpd_debounce_delay_ms)))
- drm_dbg_kms(dev, "HDMI HPD: Re-scheduled debounce work\n");
-
- } else {
-
- /* If the aconnector->hdmi_hpd_debounce_work is scheduled, exit early */
- if (delayed_work_pending(&aconnector->hdmi_hpd_debounce_work))
- return;
-
- scoped_guard(mutex, &adev->dm.dc_lock) {
- dc_exit_ips_for_hw_access(dc);
- ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
- }
- if (ret) {
- /* w/a delay for certain panels */
- apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink);
- amdgpu_dm_update_connector_after_detect(aconnector);
-
- drm_modeset_lock_all(dev);
- dm_restore_drm_connector_state(dev, connector);
- drm_modeset_unlock_all(dev);
-
- if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
- drm_kms_helper_connector_hotplug_event(connector);
- }
- }
- }
-
- static void handle_hpd_irq(void *param)
- {
- struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
-
- handle_hpd_irq_helper(aconnector);
-
- }
-
- static void schedule_hpd_rx_offload_work(struct amdgpu_device *adev, struct hpd_rx_irq_offload_work_queue *offload_wq,
- union hpd_irq_data hpd_irq_data)
- {
- struct hpd_rx_irq_offload_work *offload_work = kzalloc_obj(*offload_work);
-
- if (!offload_work) {
- drm_err(adev_to_drm(adev), "Failed to allocate hpd_rx_irq_offload_work.\n");
- return;
- }
-
- INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work);
- offload_work->data = hpd_irq_data;
- offload_work->offload_wq = offload_wq;
- offload_work->adev = adev;
-
- queue_work(offload_wq->wq, &offload_work->work);
- drm_dbg_kms(adev_to_drm(adev), "queue work to handle hpd_rx offload work");
- }
-
- static void handle_hpd_rx_irq(void *param)
- {
- struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
- struct drm_connector *connector = &aconnector->base;
- struct drm_device *dev = connector->dev;
- struct dc_link *dc_link = aconnector->dc_link;
- bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
- bool result = false;
- enum dc_connection_type new_connection_type = dc_connection_none;
- struct amdgpu_device *adev = drm_to_adev(dev);
- union hpd_irq_data hpd_irq_data;
- bool link_loss = false;
- bool has_left_work = false;
- int idx = dc_link->link_index;
- struct hpd_rx_irq_offload_work_queue *offload_wq = &adev->dm.hpd_rx_offload_wq[idx];
- struct dc *dc = aconnector->dc_link->ctx->dc;
-
- memset(&hpd_irq_data, 0, sizeof(hpd_irq_data));
-
- if (adev->dm.disable_hpd_irq)
- return;
-
- /*
- * TODO:Temporary add mutex to protect hpd interrupt not have a gpio
- * conflict, after implement i2c helper, this mutex should be
- * retired.
- */
- mutex_lock(&aconnector->hpd_lock);
-
- result = dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data,
- &link_loss, true, &has_left_work);
-
- if (!has_left_work)
- goto out;
-
- if (hpd_irq_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
- schedule_hpd_rx_offload_work(adev, offload_wq, hpd_irq_data);
- goto out;
- }
-
- if (dc_link_dp_allow_hpd_rx_irq(dc_link)) {
- if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
- hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
- bool skip = false;
-
- /*
- * DOWN_REP_MSG_RDY is also handled by polling method
- * mgr->cbs->poll_hpd_irq()
- */
- spin_lock(&offload_wq->offload_lock);
- skip = offload_wq->is_handling_mst_msg_rdy_event;
-
- if (!skip)
- offload_wq->is_handling_mst_msg_rdy_event = true;
-
- spin_unlock(&offload_wq->offload_lock);
-
- if (!skip)
- schedule_hpd_rx_offload_work(adev, offload_wq, hpd_irq_data);
-
- goto out;
- }
-
- if (link_loss) {
- bool skip = false;
-
- spin_lock(&offload_wq->offload_lock);
- skip = offload_wq->is_handling_link_loss;
-
- if (!skip)
- offload_wq->is_handling_link_loss = true;
-
- spin_unlock(&offload_wq->offload_lock);
-
- if (!skip)
- schedule_hpd_rx_offload_work(adev, offload_wq, hpd_irq_data);
-
- goto out;
- }
- }
-
- out:
- if (result && !is_mst_root_connector) {
- /* Downstream Port status changed. */
- if (!dc_link_detect_connection_type(dc_link, &new_connection_type))
- drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
-
- if (aconnector->base.force && new_connection_type == dc_connection_none) {
- emulated_link_detect(dc_link);
-
- if (aconnector->fake_enable)
- aconnector->fake_enable = false;
-
- amdgpu_dm_update_connector_after_detect(aconnector);
-
-
- drm_modeset_lock_all(dev);
- dm_restore_drm_connector_state(dev, connector);
- drm_modeset_unlock_all(dev);
-
- drm_kms_helper_connector_hotplug_event(connector);
- } else {
- bool ret = false;
-
- mutex_lock(&adev->dm.dc_lock);
- dc_exit_ips_for_hw_access(dc);
- ret = dc_link_detect(dc_link, DETECT_REASON_HPDRX);
- mutex_unlock(&adev->dm.dc_lock);
-
- if (ret) {
- if (aconnector->fake_enable)
- aconnector->fake_enable = false;
-
- amdgpu_dm_update_connector_after_detect(aconnector);
-
- drm_modeset_lock_all(dev);
- dm_restore_drm_connector_state(dev, connector);
- drm_modeset_unlock_all(dev);
-
- drm_kms_helper_connector_hotplug_event(connector);
- }
- }
- }
- if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) {
- if (adev->dm.hdcp_workqueue)
- hdcp_handle_cpirq(adev->dm.hdcp_workqueue, aconnector->base.index);
- }
-
- if (dc_link->type != dc_connection_mst_branch)
- drm_dp_cec_irq(&aconnector->dm_dp_aux.aux);
-
- mutex_unlock(&aconnector->hpd_lock);
- }
-
- static int register_hpd_handlers(struct amdgpu_device *adev)
- {
- struct drm_device *dev = adev_to_drm(adev);
- struct drm_connector *connector;
- struct amdgpu_dm_connector *aconnector;
- const struct dc_link *dc_link;
- struct dc_interrupt_params int_params = {0};
-
- int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
- int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
-
- if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
- if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD,
- dmub_hpd_callback, true)) {
- drm_err(adev_to_drm(adev), "fail to register dmub hpd callback");
- return -EINVAL;
- }
-
- if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD_IRQ,
- dmub_hpd_callback, true)) {
- drm_err(adev_to_drm(adev), "fail to register dmub hpd callback");
- return -EINVAL;
- }
-
- if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD_SENSE_NOTIFY,
- dmub_hpd_sense_callback, true)) {
- drm_err(adev_to_drm(adev), "fail to register dmub hpd sense callback");
- return -EINVAL;
- }
- }
-
- list_for_each_entry(connector,
- &dev->mode_config.connector_list, head) {
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- continue;
-
- aconnector = to_amdgpu_dm_connector(connector);
- dc_link = aconnector->dc_link;
-
- if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
- int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
- int_params.irq_source = dc_link->irq_source_hpd;
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_HPD1 ||
- int_params.irq_source > DC_IRQ_SOURCE_HPD6) {
- drm_err(adev_to_drm(adev), "Failed to register hpd irq!\n");
- return -EINVAL;
- }
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- handle_hpd_irq, (void *) aconnector))
- return -ENOMEM;
- }
-
- if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
-
- /* Also register for DP short pulse (hpd_rx). */
- int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
- int_params.irq_source = dc_link->irq_source_hpd_rx;
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_HPD1RX ||
- int_params.irq_source > DC_IRQ_SOURCE_HPD6RX) {
- drm_err(adev_to_drm(adev), "Failed to register hpd rx irq!\n");
- return -EINVAL;
- }
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- handle_hpd_rx_irq, (void *) aconnector))
- return -ENOMEM;
- }
- }
- return 0;
- }
-
- /* Register IRQ sources and initialize IRQ callbacks */
- static int dce110_register_irq_handlers(struct amdgpu_device *adev)
- {
- struct dc *dc = adev->dm.dc;
- struct common_irq_params *c_irq_params;
- struct dc_interrupt_params int_params = {0};
- int r;
- int i;
- unsigned int src_id;
- unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
- /* Use different interrupts for VBLANK on DCE 6 vs. newer. */
- const unsigned int vblank_d1 =
- adev->dm.dc->ctx->dce_version >= DCE_VERSION_8_0
- ? VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 : 1;
-
- if (adev->family >= AMDGPU_FAMILY_AI)
- client_id = SOC15_IH_CLIENTID_DCE;
-
- int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
- int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
-
- /*
- * Actions of amdgpu_irq_add_id():
- * 1. Register a set() function with base driver.
- * Base driver will call set() function to enable/disable an
- * interrupt in DC hardware.
- * 2. Register amdgpu_dm_irq_handler().
- * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
- * coming from DC hardware.
- * amdgpu_dm_irq_handler() will re-direct the interrupt to DC
- * for acknowledging and handling.
- */
-
- /* Use VBLANK interrupt */
- for (i = 0; i < adev->mode_info.num_crtc; i++) {
- src_id = vblank_d1 + i;
- r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->crtc_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, src_id, 0);
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 ||
- int_params.irq_source > DC_IRQ_SOURCE_VBLANK6) {
- drm_err(adev_to_drm(adev), "Failed to register vblank irq!\n");
- return -EINVAL;
- }
-
- c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
-
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_crtc_high_irq, c_irq_params))
- return -ENOMEM;
- }
-
- if (dc_supports_vrr(adev->dm.dc->ctx->dce_version)) {
- /* Use VUPDATE interrupt */
- for (i = 0; i < adev->mode_info.num_crtc; i++) {
- src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + i * 2;
- r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->vupdate_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, src_id, 0);
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 ||
- int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) {
- drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n");
- return -EINVAL;
- }
-
- c_irq_params = &adev->dm.vupdate_params[
- int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_vupdate_high_irq, c_irq_params))
- return -ENOMEM;
- }
- }
-
- /* Use GRPH_PFLIP interrupt */
- for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP;
- i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) {
- r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add page flip irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i, 0);
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_PFLIP_FIRST ||
- int_params.irq_source > DC_IRQ_SOURCE_PFLIP_LAST) {
- drm_err(adev_to_drm(adev), "Failed to register pflip irq!\n");
- return -EINVAL;
- }
-
- c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST];
-
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_pflip_high_irq, c_irq_params))
- return -ENOMEM;
- }
-
- /* HPD */
- r = amdgpu_irq_add_id(adev, client_id,
- VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add hpd irq id!\n");
- return r;
- }
-
- r = register_hpd_handlers(adev);
-
- return r;
- }
-
- /* Register IRQ sources and initialize IRQ callbacks */
- static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
- {
- struct dc *dc = adev->dm.dc;
- struct common_irq_params *c_irq_params;
- struct dc_interrupt_params int_params = {0};
- int r;
- int i;
- #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- static const unsigned int vrtl_int_srcid[] = {
- DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL,
- DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL,
- DCN_1_0__SRCID__OTG3_VERTICAL_INTERRUPT0_CONTROL,
- DCN_1_0__SRCID__OTG4_VERTICAL_INTERRUPT0_CONTROL,
- DCN_1_0__SRCID__OTG5_VERTICAL_INTERRUPT0_CONTROL,
- DCN_1_0__SRCID__OTG6_VERTICAL_INTERRUPT0_CONTROL
- };
- #endif
-
- int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
- int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
-
- /*
- * Actions of amdgpu_irq_add_id():
- * 1. Register a set() function with base driver.
- * Base driver will call set() function to enable/disable an
- * interrupt in DC hardware.
- * 2. Register amdgpu_dm_irq_handler().
- * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
- * coming from DC hardware.
- * amdgpu_dm_irq_handler() will re-direct the interrupt to DC
- * for acknowledging and handling.
- */
-
- /* Use otg vertical line interrupt */
- #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- for (i = 0; i <= adev->mode_info.num_crtc - 1; i++) {
- r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE,
- vrtl_int_srcid[i], &adev->vline0_irq);
-
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add vline0 irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, vrtl_int_srcid[i], 0);
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_DC1_VLINE0 ||
- int_params.irq_source > DC_IRQ_SOURCE_DC6_VLINE0) {
- drm_err(adev_to_drm(adev), "Failed to register vline0 irq!\n");
- return -EINVAL;
- }
-
- c_irq_params = &adev->dm.vline0_params[int_params.irq_source
- - DC_IRQ_SOURCE_DC1_VLINE0];
-
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_dcn_vertical_interrupt0_high_irq,
- c_irq_params))
- return -ENOMEM;
- }
- #endif
-
- /* Use VUPDATE_NO_LOCK interrupt on DCN, which seems to correspond to
- * the regular VUPDATE interrupt on DCE. We want DC_IRQ_SOURCE_VUPDATEx
- * to trigger at end of each vblank, regardless of state of the lock,
- * matching DCE behaviour.
- */
- for (i = DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT;
- i <= DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT + adev->mode_info.num_crtc - 1;
- i++) {
- r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->vupdate_irq);
-
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i, 0);
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 ||
- int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) {
- drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n");
- return -EINVAL;
- }
-
- c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
-
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_vupdate_high_irq, c_irq_params))
- return -ENOMEM;
- }
-
- /* HPD */
- r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT,
- &adev->hpd_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add hpd irq id!\n");
- return r;
- }
-
- r = register_hpd_handlers(adev);
-
- return r;
- }
- /* Register Outbox IRQ sources and initialize IRQ callbacks */
- static int register_outbox_irq_handlers(struct amdgpu_device *adev)
- {
- struct dc *dc = adev->dm.dc;
- struct common_irq_params *c_irq_params;
- struct dc_interrupt_params int_params = {0};
- int r, i;
-
- int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
- int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
-
- r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT,
- &adev->dmub_outbox_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add outbox irq id!\n");
- return r;
- }
-
- if (dc->ctx->dmub_srv) {
- i = DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT;
- int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i, 0);
-
- c_irq_params = &adev->dm.dmub_outbox_params[0];
-
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_dmub_outbox1_low_irq, c_irq_params))
- return -ENOMEM;
- }
-
- return 0;
- }
-
/*
* Acquires the lock for the atomic state object and returns
* the new atomic state.
@@@ -5196,420 -2401,6 +2401,6 @@@ static int amdgpu_dm_mode_config_init(s
return 0;
}
- #define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12
- #define AMDGPU_DM_DEFAULT_MAX_BACKLIGHT 255
- #define AMDGPU_DM_MIN_SPREAD ((AMDGPU_DM_DEFAULT_MAX_BACKLIGHT - AMDGPU_DM_DEFAULT_MIN_BACKLIGHT) / 2)
- #define AUX_BL_DEFAULT_TRANSITION_TIME_MS 50
-
- void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
- int bl_idx)
- {
- struct amdgpu_dm_backlight_caps *caps = &dm->backlight_caps[bl_idx];
-
- if (caps->caps_valid)
- return;
-
- #if defined(CONFIG_ACPI)
- amdgpu_acpi_get_backlight_caps(caps);
-
- /* validate the firmware value is sane */
- if (caps->caps_valid) {
- int spread = caps->max_input_signal - caps->min_input_signal;
-
- if (caps->max_input_signal > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT ||
- caps->min_input_signal < 0 ||
- spread > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT ||
- spread < AMDGPU_DM_MIN_SPREAD) {
- drm_dbg_kms(adev_to_drm(dm->adev), "DM: Invalid backlight caps: min=%d, max=%d\n",
- caps->min_input_signal, caps->max_input_signal);
- caps->caps_valid = false;
- }
- }
-
- if (!caps->caps_valid) {
- caps->min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
- caps->max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
- caps->caps_valid = true;
- }
- #else
- if (caps->aux_support)
- return;
-
- caps->min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
- caps->max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
- caps->caps_valid = true;
- #endif
- }
-
- static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
- unsigned int *min, unsigned int *max)
- {
- if (!caps)
- return 0;
-
- if (caps->aux_support) {
- // Firmware limits are in nits, DC API wants millinits.
- *max = 1000 * caps->aux_max_input_signal;
- *min = 1000 * caps->aux_min_input_signal;
- } else {
- // Firmware limits are 8-bit, PWM control is 16-bit.
- *max = 0x101 * caps->max_input_signal;
- *min = 0x101 * caps->min_input_signal;
- }
- return 1;
- }
-
- /* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */
- static inline u32 scale_input_to_fw(int min, int max, u64 input)
- {
- return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max - min);
- }
-
- /* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */
- static inline u32 scale_fw_to_input(int min, int max, u64 input)
- {
- return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), AMDGPU_MAX_BL_LEVEL);
- }
-
- static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
- unsigned int min, unsigned int max,
- uint32_t *user_brightness)
- {
- u32 brightness = scale_input_to_fw(min, max, *user_brightness);
- u8 lower_signal, upper_signal, upper_lum, lower_lum, lum;
- int left, right;
-
- if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)
- return;
-
- if (!caps->data_points)
- return;
-
- /*
- * Handle the case where brightness is below the first data point
- * Interpolate between (0,0) and (first_signal, first_lum)
- */
- if (brightness < caps->luminance_data[0].input_signal) {
- lum = DIV_ROUND_CLOSEST(caps->luminance_data[0].luminance * brightness,
- caps->luminance_data[0].input_signal);
- goto scale;
- }
-
- left = 0;
- right = caps->data_points - 1;
- while (left <= right) {
- int mid = left + (right - left) / 2;
- u8 signal = caps->luminance_data[mid].input_signal;
-
- /* Exact match found */
- if (signal == brightness) {
- lum = caps->luminance_data[mid].luminance;
- goto scale;
- }
-
- if (signal < brightness)
- left = mid + 1;
- else
- right = mid - 1;
- }
-
- /* verify bound */
- if (left >= caps->data_points)
- left = caps->data_points - 1;
-
- /* At this point, left > right */
- lower_signal = caps->luminance_data[right].input_signal;
- upper_signal = caps->luminance_data[left].input_signal;
- lower_lum = caps->luminance_data[right].luminance;
- upper_lum = caps->luminance_data[left].luminance;
-
- /* interpolate */
- if (right == left || !lower_lum)
- lum = upper_lum;
- else
- lum = lower_lum + DIV_ROUND_CLOSEST((upper_lum - lower_lum) *
- (brightness - lower_signal),
- upper_signal - lower_signal);
- scale:
- *user_brightness = scale_fw_to_input(min, max,
- DIV_ROUND_CLOSEST(lum * brightness, 101));
- }
-
- static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
- uint32_t brightness)
- {
- unsigned int min, max;
-
- if (!get_brightness_range(caps, &min, &max))
- return brightness;
-
- convert_custom_brightness(caps, min, max, &brightness);
-
- // Rescale 0..max to min..max
- return min + DIV_ROUND_CLOSEST_ULL((u64)(max - min) * brightness, max);
- }
-
- static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
- uint32_t brightness)
- {
- unsigned int min, max;
-
- if (!get_brightness_range(caps, &min, &max))
- return brightness;
-
- if (brightness < min)
- return 0;
- // Rescale min..max to 0..max
- return DIV_ROUND_CLOSEST_ULL((u64)max * (brightness - min),
- max - min);
- }
-
- static struct dc_stream_state *dm_find_stream_with_link(
- struct amdgpu_display_manager *dm,
- struct dc_link *link)
- {
- struct dc_state *cur_dc_state = dm->dc->current_state;
- struct dc_stream_state *stream = NULL;
- int i;
-
- for (i = 0; i < cur_dc_state->stream_count; i++) {
- stream = cur_dc_state->streams[i];
- if (stream->link == link)
- return stream;
- }
-
- return NULL;
- }
-
- static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
- int bl_idx,
- u32 user_brightness)
- {
- struct amdgpu_dm_backlight_caps *caps;
- struct dc_link *link;
- u32 brightness = 0;
- bool rc = false, reallow_idle = false;
- struct drm_connector *connector;
- struct dc_stream_state *stream;
- unsigned int min, max;
-
- list_for_each_entry(connector, &dm->ddev->mode_config.connector_list, head) {
- struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
-
- if (aconnector->bl_idx != bl_idx)
- continue;
-
- /* if connector is off, save the brightness for next time it's on */
- if (!aconnector->base.encoder) {
- dm->brightness[bl_idx] = user_brightness;
- dm->actual_brightness[bl_idx] = 0;
- return;
- }
- }
-
- amdgpu_dm_update_backlight_caps(dm, bl_idx);
- caps = &dm->backlight_caps[bl_idx];
-
- dm->brightness[bl_idx] = user_brightness;
- /* update scratch register */
- if (bl_idx == 0)
- amdgpu_atombios_scratch_regs_set_backlight_level(dm->adev, dm->brightness[bl_idx]);
- brightness = convert_brightness_from_user(caps, dm->brightness[bl_idx]);
- link = (struct dc_link *)dm->backlight_link[bl_idx];
-
- /* Apply brightness quirk */
- if (caps->brightness_mask)
- brightness |= caps->brightness_mask;
-
- if (trace_amdgpu_dm_brightness_enabled()) {
- trace_amdgpu_dm_brightness(__builtin_return_address(0),
- user_brightness,
- brightness,
- caps->aux_support,
- power_supply_is_system_supplied() > 0);
- }
-
- stream = dm_find_stream_with_link(dm, link);
- if (!stream)
- return;
-
- mutex_lock(&dm->dc_lock);
- if (dm->dc->caps.ips_support && dm->dc->ctx->dmub_srv->idle_allowed) {
- dc_allow_idle_optimizations(dm->dc, false);
- reallow_idle = true;
- }
-
- if (caps->aux_support) {
- rc = mod_power_set_backlight_nits(dm->power_module, stream, brightness,
- AUX_BL_DEFAULT_TRANSITION_TIME_MS, false, true);
- } else {
- /* power module uses millipercent */
- get_brightness_range(caps, &min, &max);
- brightness = DIV_ROUND_CLOSEST(brightness * 100, (max - min)) * 1000;
- rc = mod_power_set_backlight_percent(dm->power_module, stream,
- brightness, 0, false);
- }
-
- /*
- * Some kms clients create a ramped backlight transition effect
- * by rapidly changing the backlight. Yet we must wait on dmcub
- * fw to exit psr/replay before programming backlight. To
- * prevent lag, keep disable psr/replay and let the next atomic
- * flip clear the event.
- *
- * ToDo: use ISM to handle rapidly backlight change
- *
- * Rapidly backlight change is similar to rapidly cursor events,
- * which is now handled by ISM. ISM can delay the event until system
- * is really idle, so we may use ISM to handle backlight change as well.
- */
- amdgpu_dm_psr_set_event(dm, stream, true,
- psr_event_hw_programming, true);
- amdgpu_dm_replay_set_event(dm, stream, true,
- replay_event_hw_programming, true);
-
- if (dm->dc->caps.ips_support && reallow_idle)
- dc_allow_idle_optimizations(dm->dc, true);
-
- mutex_unlock(&dm->dc_lock);
-
- if (rc)
- dm->actual_brightness[bl_idx] = user_brightness;
- }
-
- static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
- {
- struct amdgpu_display_manager *dm = bl_get_data(bd);
- int i;
-
- for (i = 0; i < dm->num_of_edps; i++) {
- if (bd == dm->backlight_dev[i])
- break;
- }
- if (i >= AMDGPU_DM_MAX_NUM_EDP)
- i = 0;
- amdgpu_dm_backlight_set_level(dm, i, bd->props.brightness);
-
- return 0;
- }
-
- static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm,
- int bl_idx)
- {
- int ret;
- struct amdgpu_dm_backlight_caps caps;
- struct dc_link *link = (struct dc_link *)dm->backlight_link[bl_idx];
-
- amdgpu_dm_update_backlight_caps(dm, bl_idx);
- caps = dm->backlight_caps[bl_idx];
-
- if (caps.aux_support) {
- u32 avg, peak;
-
- if (!dc_link_get_backlight_level_nits(link, &avg, &peak))
- return dm->brightness[bl_idx];
- return convert_brightness_to_user(&caps, avg);
- }
-
- ret = dc_link_get_backlight_level(link);
-
- if (ret == DC_ERROR_UNEXPECTED)
- return dm->brightness[bl_idx];
-
- return convert_brightness_to_user(&caps, ret);
- }
-
- static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
- {
- struct amdgpu_display_manager *dm = bl_get_data(bd);
- int i;
-
- for (i = 0; i < dm->num_of_edps; i++) {
- if (bd == dm->backlight_dev[i])
- break;
- }
- if (i >= AMDGPU_DM_MAX_NUM_EDP)
- i = 0;
- return amdgpu_dm_backlight_get_level(dm, i);
- }
-
- static const struct backlight_ops amdgpu_dm_backlight_ops = {
- .options = BL_CORE_SUSPENDRESUME,
- .get_brightness = amdgpu_dm_backlight_get_brightness,
- .update_status = amdgpu_dm_backlight_update_status,
- };
-
- static void
- amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
- {
- struct drm_device *drm = aconnector->base.dev;
- struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm;
- struct backlight_properties props = { 0 };
- struct amdgpu_dm_backlight_caps *caps;
- char bl_name[16];
- int min, max;
- int real_brightness;
- int init_brightness;
-
- if (aconnector->bl_idx == -1)
- return;
-
- if (!acpi_video_backlight_use_native()) {
- drm_info(drm, "Skipping amdgpu DM backlight registration\n");
- /* Try registering an ACPI video backlight device instead. */
- acpi_video_register_backlight();
- return;
- }
-
- caps = &dm->backlight_caps[aconnector->bl_idx];
- if (get_brightness_range(caps, &min, &max)) {
- if (power_supply_is_system_supplied() > 0)
- props.brightness = DIV_ROUND_CLOSEST(max * caps->ac_level, 100);
- else
- props.brightness = DIV_ROUND_CLOSEST(max * caps->dc_level, 100);
- /* min is zero, so max needs to be adjusted */
- props.max_brightness = max;
- drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max,
- caps->ac_level, caps->dc_level);
- } else
- props.brightness = props.max_brightness = MAX_BACKLIGHT_LEVEL;
-
- init_brightness = props.brightness;
-
- if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) {
- drm_info(drm, "Using custom brightness curve\n");
- props.scale = BACKLIGHT_SCALE_NON_LINEAR;
- } else
- props.scale = BACKLIGHT_SCALE_LINEAR;
- props.type = BACKLIGHT_RAW;
-
- snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
- drm->primary->index + aconnector->bl_idx);
-
- dm->backlight_dev[aconnector->bl_idx] =
- backlight_device_register(bl_name, aconnector->base.kdev, dm,
- &amdgpu_dm_backlight_ops, &props);
- dm->brightness[aconnector->bl_idx] = props.brightness;
-
- if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) {
- drm_err(drm, "DM: Backlight registration failed!\n");
- dm->backlight_dev[aconnector->bl_idx] = NULL;
- } else {
- /*
- * dm->brightness[x] can be inconsistent just after startup until
- * ops.get_brightness is called.
- */
- real_brightness =
- amdgpu_dm_backlight_ops.get_brightness(dm->backlight_dev[aconnector->bl_idx]);
-
- if (real_brightness != init_brightness) {
- dm->actual_brightness[aconnector->bl_idx] = real_brightness;
- dm->brightness[aconnector->bl_idx] = real_brightness;
- }
- drm_dbg_driver(drm, "DM: Registered Backlight device: %s\n", bl_name);
- }
- }
-
static int initialize_plane(struct amdgpu_display_manager *dm,
struct amdgpu_mode_info *mode_info, int plane_id,
enum drm_plane_type plane_type,
@@@ -5651,42 -2442,6 +2442,6 @@@
}
- static void setup_backlight_device(struct amdgpu_display_manager *dm,
- struct amdgpu_dm_connector *aconnector)
- {
- struct amdgpu_dm_backlight_caps *caps;
- struct dc_link *link = aconnector->dc_link;
- int bl_idx = dm->num_of_edps;
-
- if (!(link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) ||
- link->type == dc_connection_none)
- return;
-
- if (dm->num_of_edps >= AMDGPU_DM_MAX_NUM_EDP) {
- drm_warn(adev_to_drm(dm->adev), "Too much eDP connections, skipping backlight setup for additional eDPs\n");
- return;
- }
-
- aconnector->bl_idx = bl_idx;
-
- amdgpu_dm_update_backlight_caps(dm, bl_idx);
- dm->backlight_link[bl_idx] = link;
- dm->num_of_edps++;
-
- update_connector_ext_caps(aconnector);
- caps = &dm->backlight_caps[aconnector->bl_idx];
-
- /* Only offer ABM property when non-OLED and user didn't turn off by module parameter */
- if (caps->ext_caps && !caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0)
- drm_object_attach_property(&aconnector->base.base,
- dm->adev->mode_info.abm_level_property,
- ABM_SYSFS_CONTROL);
- }
-
- static void amdgpu_set_panel_orientation(struct drm_connector *connector);
-
-
-
/*
* In this architecture, the association
* connector -> encoder -> crtc
@@@ -5798,7 -2553,7 +2553,7 @@@ static int amdgpu_dm_initialize_drm_dev
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 1):
- if (register_outbox_irq_handlers(dm->adev)) {
+ if (amdgpu_dm_register_outbox_irq_handlers(dm->adev)) {
drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
goto fail;
}
@@@ -5911,7 -2666,7 +2666,7 @@@
drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
if (aconnector->base.force && new_connection_type == dc_connection_none) {
- emulated_link_detect(link);
+ amdgpu_dm_emulated_link_detect(link);
amdgpu_dm_update_connector_after_detect(aconnector);
} else {
bool ret = false;
@@@ -5923,7 -2678,7 +2678,7 @@@
if (ret) {
amdgpu_dm_update_connector_after_detect(aconnector);
- setup_backlight_device(dm, aconnector);
+ amdgpu_dm_setup_backlight_device(dm, aconnector);
/* Disable PSR if Replay can be enabled */
if (replay_feature_enabled)
@@@ -5975,7 -2730,7 +2730,7 @@@
case CHIP_VEGA10:
case CHIP_VEGA12:
case CHIP_VEGA20:
- if (dce110_register_irq_handlers(dm->adev)) {
+ if (amdgpu_dm_dce110_register_irq_handlers(dm->adev)) {
drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
goto fail;
}
@@@ -6005,7 -2760,7 +2760,7 @@@
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 1):
- if (dcn10_register_irq_handlers(dm->adev)) {
+ if (amdgpu_dm_dcn10_register_irq_handlers(dm->adev)) {
drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
goto fail;
}
@@@ -6096,78 -2851,6 +2851,6 @@@ DEVICE_ATTR_WO(s3_debug)
#endif
- static int dm_init_microcode(struct amdgpu_device *adev)
- {
- char *fw_name_dmub;
- int r;
-
- switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
- case IP_VERSION(2, 1, 0):
- fw_name_dmub = FIRMWARE_RENOIR_DMUB;
- if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
- fw_name_dmub = FIRMWARE_GREEN_SARDINE_DMUB;
- break;
- case IP_VERSION(3, 0, 0):
- if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 3, 0))
- fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB;
- else
- fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB;
- break;
- case IP_VERSION(3, 0, 1):
- fw_name_dmub = FIRMWARE_VANGOGH_DMUB;
- break;
- case IP_VERSION(3, 0, 2):
- fw_name_dmub = FIRMWARE_DIMGREY_CAVEFISH_DMUB;
- break;
- case IP_VERSION(3, 0, 3):
- fw_name_dmub = FIRMWARE_BEIGE_GOBY_DMUB;
- break;
- case IP_VERSION(3, 1, 2):
- case IP_VERSION(3, 1, 3):
- fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB;
- break;
- case IP_VERSION(3, 1, 4):
- fw_name_dmub = FIRMWARE_DCN_314_DMUB;
- break;
- case IP_VERSION(3, 1, 5):
- fw_name_dmub = FIRMWARE_DCN_315_DMUB;
- break;
- case IP_VERSION(3, 1, 6):
- fw_name_dmub = FIRMWARE_DCN316_DMUB;
- break;
- case IP_VERSION(3, 2, 0):
- fw_name_dmub = FIRMWARE_DCN_V3_2_0_DMCUB;
- break;
- case IP_VERSION(3, 2, 1):
- fw_name_dmub = FIRMWARE_DCN_V3_2_1_DMCUB;
- break;
- case IP_VERSION(3, 5, 0):
- fw_name_dmub = FIRMWARE_DCN_35_DMUB;
- break;
- case IP_VERSION(3, 5, 1):
- fw_name_dmub = FIRMWARE_DCN_351_DMUB;
- break;
- case IP_VERSION(3, 6, 0):
- fw_name_dmub = FIRMWARE_DCN_36_DMUB;
- break;
- case IP_VERSION(4, 0, 1):
- fw_name_dmub = FIRMWARE_DCN_401_DMUB;
- break;
- case IP_VERSION(4, 2, 0):
- fw_name_dmub = FIRMWARE_DCN_42_DMUB;
- break;
- case IP_VERSION(4, 2, 1):
- fw_name_dmub = FIRMWARE_DCN_42B_DMUB;
- break;
- default:
- /* ASIC doesn't support DMUB. */
- return 0;
- }
- r = amdgpu_ucode_request(adev, &adev->dm.dmub_fw, AMDGPU_UCODE_REQUIRED,
- "%s", fw_name_dmub);
- return r;
- }
-
static int dm_early_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@@ -6318,22 -3001,13 +3001,13 @@@
return dm_init_microcode(adev);
}
- static bool modereset_required(struct drm_crtc_state *crtc_state)
+ STATIC_IFN_KUNIT bool modereset_required(struct drm_crtc_state *crtc_state)
{
return !crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state);
}
+ EXPORT_IF_KUNIT(modereset_required);
- static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
- {
- drm_encoder_cleanup(encoder);
- kfree(encoder);
- }
-
- static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
- .destroy = amdgpu_dm_encoder_destroy,
- };
-
- static int
+ STATIC_IFN_KUNIT int
fill_plane_color_attributes(const struct drm_plane_state *plane_state,
const enum surface_pixel_format format,
enum dc_color_space *color_space)
@@@ -6380,6 -3054,7 +3054,7 @@@
return 0;
}
+ EXPORT_IF_KUNIT(fill_plane_color_attributes);
static int
fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
@@@ -6718,7 -3393,7 +3393,7 @@@ ffu
&flip_addrs->dirty_rect_count, true);
}
- static void update_stream_scaling_settings(struct drm_device *dev,
+ void amdgpu_dm_update_stream_scaling_settings(struct drm_device *dev,
const struct drm_display_mode *mode,
const struct dm_connector_state *dm_state,
struct dc_stream_state *stream)
@@@ -6774,2063 -3449,6 +3449,6 @@@
}
- static enum dc_color_depth
- convert_color_depth_from_display_info(const struct drm_connector *connector,
- bool is_y420, int requested_bpc)
- {
- u8 bpc;
-
- if (is_y420) {
- bpc = 8;
-
- /* Cap display bpc based on HDMI 2.0 HF-VSDB */
- if (connector->display_info.hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)
- bpc = 16;
- else if (connector->display_info.hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
- bpc = 12;
- else if (connector->display_info.hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
- bpc = 10;
- } else {
- bpc = (uint8_t)connector->display_info.bpc;
- /* Assume 8 bpc by default if no bpc is specified. */
- bpc = bpc ? bpc : 8;
- }
-
- if (requested_bpc > 0) {
- /*
- * Cap display bpc based on the user requested value.
- *
- * The value for state->max_bpc may not correctly updated
- * depending on when the connector gets added to the state
- * or if this was called outside of atomic check, so it
- * can't be used directly.
- */
- bpc = min_t(u8, bpc, requested_bpc);
-
- /* Round down to the nearest even number. */
- bpc = bpc - (bpc & 1);
- }
-
- switch (bpc) {
- case 0:
- /*
- * Temporary Work around, DRM doesn't parse color depth for
- * EDID revision before 1.4
- * TODO: Fix edid parsing
- */
- return COLOR_DEPTH_888;
- case 6:
- return COLOR_DEPTH_666;
- case 8:
- return COLOR_DEPTH_888;
- case 10:
- return COLOR_DEPTH_101010;
- case 12:
- return COLOR_DEPTH_121212;
- case 14:
- return COLOR_DEPTH_141414;
- case 16:
- return COLOR_DEPTH_161616;
- default:
- return COLOR_DEPTH_UNDEFINED;
- }
- }
-
- static enum dc_aspect_ratio
- get_aspect_ratio(const struct drm_display_mode *mode_in)
- {
- /* 1-1 mapping, since both enums follow the HDMI spec. */
- return (enum dc_aspect_ratio) mode_in->picture_aspect_ratio;
- }
-
- static enum dc_color_space
- get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
- const struct drm_connector_state *connector_state)
- {
- enum dc_color_space color_space = COLOR_SPACE_SRGB;
-
- switch (connector_state->colorspace) {
- case DRM_MODE_COLORIMETRY_BT601_YCC:
- if (dc_crtc_timing->flags.Y_ONLY)
- color_space = COLOR_SPACE_YCBCR601_LIMITED;
- else
- color_space = COLOR_SPACE_YCBCR601;
- break;
- case DRM_MODE_COLORIMETRY_BT709_YCC:
- if (dc_crtc_timing->flags.Y_ONLY)
- color_space = COLOR_SPACE_YCBCR709_LIMITED;
- else
- color_space = COLOR_SPACE_YCBCR709;
- break;
- case DRM_MODE_COLORIMETRY_OPRGB:
- color_space = COLOR_SPACE_ADOBERGB;
- break;
- case DRM_MODE_COLORIMETRY_BT2020_RGB:
- case DRM_MODE_COLORIMETRY_BT2020_YCC:
- if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
- color_space = COLOR_SPACE_2020_RGB_FULLRANGE;
- else
- color_space = COLOR_SPACE_2020_YCBCR_LIMITED;
- break;
- case DRM_MODE_COLORIMETRY_DEFAULT: // ITU601
- default:
- if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) {
- color_space = COLOR_SPACE_SRGB;
- if (connector_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)
- color_space = COLOR_SPACE_SRGB_LIMITED;
- /*
- * 27030khz is the separation point between HDTV and SDTV
- * according to HDMI spec, we use YCbCr709 and YCbCr601
- * respectively
- */
- } else if (dc_crtc_timing->pix_clk_100hz > 270300) {
- if (dc_crtc_timing->flags.Y_ONLY)
- color_space =
- COLOR_SPACE_YCBCR709_LIMITED;
- else
- color_space = COLOR_SPACE_YCBCR709;
- } else {
- if (dc_crtc_timing->flags.Y_ONLY)
- color_space =
- COLOR_SPACE_YCBCR601_LIMITED;
- else
- color_space = COLOR_SPACE_YCBCR601;
- }
- break;
- }
-
- return color_space;
- }
-
- static enum display_content_type
- get_output_content_type(const struct drm_connector_state *connector_state)
- {
- switch (connector_state->content_type) {
- default:
- case DRM_MODE_CONTENT_TYPE_NO_DATA:
- return DISPLAY_CONTENT_TYPE_NO_DATA;
- case DRM_MODE_CONTENT_TYPE_GRAPHICS:
- return DISPLAY_CONTENT_TYPE_GRAPHICS;
- case DRM_MODE_CONTENT_TYPE_PHOTO:
- return DISPLAY_CONTENT_TYPE_PHOTO;
- case DRM_MODE_CONTENT_TYPE_CINEMA:
- return DISPLAY_CONTENT_TYPE_CINEMA;
- case DRM_MODE_CONTENT_TYPE_GAME:
- return DISPLAY_CONTENT_TYPE_GAME;
- }
- }
-
- static bool adjust_colour_depth_from_display_info(
- struct dc_crtc_timing *timing_out,
- const struct drm_display_info *info)
- {
- enum dc_color_depth depth = timing_out->display_color_depth;
- int normalized_clk;
-
- do {
- normalized_clk = timing_out->pix_clk_100hz / 10;
- /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
- if (timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420)
- normalized_clk /= 2;
- /* Adjusting pix clock following on HDMI spec based on colour depth */
- switch (depth) {
- case COLOR_DEPTH_888:
- break;
- case COLOR_DEPTH_101010:
- normalized_clk = (normalized_clk * 30) / 24;
- break;
- case COLOR_DEPTH_121212:
- normalized_clk = (normalized_clk * 36) / 24;
- break;
- case COLOR_DEPTH_161616:
- normalized_clk = (normalized_clk * 48) / 24;
- break;
- default:
- /* The above depths are the only ones valid for HDMI. */
- return false;
- }
- if (normalized_clk <= info->max_tmds_clock) {
- timing_out->display_color_depth = depth;
- return true;
- }
- } while (--depth > COLOR_DEPTH_666);
- return false;
- }
-
- static void fill_stream_properties_from_drm_display_mode(
- struct dc_stream_state *stream,
- const struct drm_display_mode *mode_in,
- const struct drm_connector *connector,
- const struct drm_connector_state *connector_state,
- const struct dc_stream_state *old_stream,
- int requested_bpc)
- {
- struct dc_crtc_timing *timing_out = &stream->timing;
- const struct drm_display_info *info = &connector->display_info;
- struct amdgpu_dm_connector *aconnector = NULL;
- struct hdmi_vendor_infoframe hv_frame;
- struct hdmi_avi_infoframe avi_frame;
- ssize_t err;
-
- if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
- aconnector = to_amdgpu_dm_connector(connector);
-
- memset(&hv_frame, 0, sizeof(hv_frame));
- memset(&avi_frame, 0, sizeof(avi_frame));
-
- timing_out->h_border_left = 0;
- timing_out->h_border_right = 0;
- timing_out->v_border_top = 0;
- timing_out->v_border_bottom = 0;
- /* TODO: un-hardcode */
- if (drm_mode_is_420_only(info, mode_in)
- && (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
- stream->signal == SIGNAL_TYPE_HDMI_FRL)
- && aconnector
- && aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR420)
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- else if (drm_mode_is_420_also(info, mode_in)
- && aconnector
- && (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR420
- || aconnector->force_yuv420_output))
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
- && aconnector
- && (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR422
- || aconnector->force_yuv422_output))
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422;
- else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
- && (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
- stream->signal == SIGNAL_TYPE_HDMI_FRL)
- && aconnector
- && aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR444)
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
- else
- timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
-
- timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
- timing_out->display_color_depth = convert_color_depth_from_display_info(
- connector,
- (timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420),
- requested_bpc);
- timing_out->scan_type = SCANNING_TYPE_NODATA;
- timing_out->hdmi_vic = 0;
-
- if (old_stream) {
- timing_out->vic = old_stream->timing.vic;
- timing_out->flags.HSYNC_POSITIVE_POLARITY = old_stream->timing.flags.HSYNC_POSITIVE_POLARITY;
- timing_out->flags.VSYNC_POSITIVE_POLARITY = old_stream->timing.flags.VSYNC_POSITIVE_POLARITY;
- } else {
- timing_out->vic = drm_match_cea_mode(mode_in);
- if (mode_in->flags & DRM_MODE_FLAG_PHSYNC)
- timing_out->flags.HSYNC_POSITIVE_POLARITY = 1;
- if (mode_in->flags & DRM_MODE_FLAG_PVSYNC)
- timing_out->flags.VSYNC_POSITIVE_POLARITY = 1;
- }
-
- if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
- stream->signal == SIGNAL_TYPE_HDMI_FRL) {
- err = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame,
- (struct drm_connector *)connector,
- mode_in);
- if (err < 0)
- drm_warn_once(connector->dev, "Failed to setup avi infoframe on connector %s: %zd\n",
- connector->name, err);
- timing_out->vic = avi_frame.video_code;
- err = drm_hdmi_vendor_infoframe_from_display_mode(&hv_frame,
- (struct drm_connector *)connector,
- mode_in);
- if (err < 0)
- drm_warn_once(connector->dev, "Failed to setup vendor infoframe on connector %s: %zd\n",
- connector->name, err);
- timing_out->hdmi_vic = hv_frame.vic;
- }
-
- if (aconnector && is_freesync_video_mode(mode_in, aconnector)) {
- timing_out->h_addressable = mode_in->hdisplay;
- timing_out->h_total = mode_in->htotal;
- timing_out->h_sync_width = mode_in->hsync_end - mode_in->hsync_start;
- timing_out->h_front_porch = mode_in->hsync_start - mode_in->hdisplay;
- timing_out->v_total = mode_in->vtotal;
- timing_out->v_addressable = mode_in->vdisplay;
- timing_out->v_front_porch = mode_in->vsync_start - mode_in->vdisplay;
- timing_out->v_sync_width = mode_in->vsync_end - mode_in->vsync_start;
- timing_out->pix_clk_100hz = mode_in->clock * 10;
- } else {
- timing_out->h_addressable = mode_in->crtc_hdisplay;
- timing_out->h_total = mode_in->crtc_htotal;
- timing_out->h_sync_width = mode_in->crtc_hsync_end - mode_in->crtc_hsync_start;
- timing_out->h_front_porch = mode_in->crtc_hsync_start - mode_in->crtc_hdisplay;
- timing_out->v_total = mode_in->crtc_vtotal;
- timing_out->v_addressable = mode_in->crtc_vdisplay;
- timing_out->v_front_porch = mode_in->crtc_vsync_start - mode_in->crtc_vdisplay;
- timing_out->v_sync_width = mode_in->crtc_vsync_end - mode_in->crtc_vsync_start;
- timing_out->pix_clk_100hz = mode_in->crtc_clock * 10;
- }
-
- timing_out->aspect_ratio = get_aspect_ratio(mode_in);
-
- stream->out_transfer_func.type = TF_TYPE_PREDEFINED;
- stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB;
- if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
- if (!adjust_colour_depth_from_display_info(timing_out, info) &&
- drm_mode_is_420_also(info, mode_in) &&
- timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) {
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- adjust_colour_depth_from_display_info(timing_out, info);
- }
- }
-
- stream->output_color_space = get_output_color_space(timing_out, connector_state);
- stream->content_type = get_output_content_type(connector_state);
- }
-
- static void fill_audio_info(struct audio_info *audio_info,
- const struct drm_connector *drm_connector,
- const struct dc_sink *dc_sink)
- {
- int i = 0;
- int cea_revision = 0;
- const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps;
-
- audio_info->manufacture_id = edid_caps->manufacturer_id;
- audio_info->product_id = edid_caps->product_id;
-
- cea_revision = drm_connector->display_info.cea_rev;
-
- strscpy(audio_info->display_name,
- edid_caps->display_name,
- AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
-
- if (cea_revision >= 3) {
- audio_info->mode_count = edid_caps->audio_mode_count;
-
- for (i = 0; i < audio_info->mode_count; ++i) {
- audio_info->modes[i].format_code =
- (enum audio_format_code)
- (edid_caps->audio_modes[i].format_code);
- audio_info->modes[i].channel_count =
- edid_caps->audio_modes[i].channel_count;
- audio_info->modes[i].sample_rates.all =
- edid_caps->audio_modes[i].sample_rate;
- audio_info->modes[i].sample_size =
- edid_caps->audio_modes[i].sample_size;
- }
- }
-
- audio_info->flags.all = edid_caps->speaker_flags;
-
- /* TODO: We only check for the progressive mode, check for interlace mode too */
- if (drm_connector->latency_present[0]) {
- audio_info->video_latency = drm_connector->video_latency[0];
- audio_info->audio_latency = drm_connector->audio_latency[0];
- }
-
- /* TODO: For DP, video and audio latency should be calculated from DPCD caps */
-
- }
-
- static void
- copy_crtc_timing_for_drm_display_mode(const struct drm_display_mode *src_mode,
- struct drm_display_mode *dst_mode)
- {
- dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay;
- dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay;
- dst_mode->crtc_clock = src_mode->crtc_clock;
- dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start;
- dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end;
- dst_mode->crtc_hsync_start = src_mode->crtc_hsync_start;
- dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end;
- dst_mode->crtc_htotal = src_mode->crtc_htotal;
- dst_mode->crtc_hskew = src_mode->crtc_hskew;
- dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;
- dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;
- dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;
- dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;
- dst_mode->crtc_vtotal = src_mode->crtc_vtotal;
- }
-
- static void
- decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode,
- const struct drm_display_mode *native_mode,
- bool scale_enabled)
- {
- if (scale_enabled || (
- native_mode->clock == drm_mode->clock &&
- native_mode->htotal == drm_mode->htotal &&
- native_mode->vtotal == drm_mode->vtotal)) {
- if (native_mode->crtc_clock)
- copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
- } else {
- /* no scaling nor amdgpu inserted, no need to patch */
- }
- }
-
- static struct dc_sink *
- create_fake_sink(struct drm_device *dev, struct dc_link *link)
- {
- struct dc_sink_init_data sink_init_data = { 0 };
- struct dc_sink *sink = NULL;
-
- sink_init_data.link = link;
- sink_init_data.sink_signal = link->connector_signal;
-
- sink = dc_sink_create(&sink_init_data);
- if (!sink) {
- drm_err(dev, "Failed to create sink!\n");
- return NULL;
- }
- sink->sink_signal = SIGNAL_TYPE_VIRTUAL;
-
- return sink;
- }
-
- static void set_multisync_trigger_params(
- struct dc_stream_state *stream)
- {
- struct dc_stream_state *master = NULL;
-
- if (stream->triggered_crtc_reset.enabled) {
- master = stream->triggered_crtc_reset.event_source;
- stream->triggered_crtc_reset.event =
- master->timing.flags.VSYNC_POSITIVE_POLARITY ?
- CRTC_EVENT_VSYNC_RISING : CRTC_EVENT_VSYNC_FALLING;
- stream->triggered_crtc_reset.delay = TRIGGER_DELAY_NEXT_PIXEL;
- }
- }
-
- static void set_master_stream(struct dc_stream_state *stream_set[],
- int stream_count)
- {
- int j, highest_rfr = 0, master_stream = 0;
-
- for (j = 0; j < stream_count; j++) {
- if (stream_set[j] && stream_set[j]->triggered_crtc_reset.enabled) {
- int refresh_rate = 0;
-
- refresh_rate = (stream_set[j]->timing.pix_clk_100hz*100)/
- (stream_set[j]->timing.h_total*stream_set[j]->timing.v_total);
- if (refresh_rate > highest_rfr) {
- highest_rfr = refresh_rate;
- master_stream = j;
- }
- }
- }
- for (j = 0; j < stream_count; j++) {
- if (stream_set[j])
- stream_set[j]->triggered_crtc_reset.event_source = stream_set[master_stream];
- }
- }
-
- static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context)
- {
- int i = 0;
- struct dc_stream_state *stream;
-
- if (context->stream_count < 2)
- return;
- for (i = 0; i < context->stream_count ; i++) {
- if (!context->streams[i])
- continue;
- /*
- * TODO: add a function to read AMD VSDB bits and set
- * crtc_sync_master.multi_sync_enabled flag
- * For now it's set to false
- */
- }
-
- set_master_stream(context->streams, context->stream_count);
-
- for (i = 0; i < context->stream_count ; i++) {
- stream = context->streams[i];
-
- if (!stream)
- continue;
-
- set_multisync_trigger_params(stream);
- }
- }
-
- /**
- * DOC: FreeSync Video
- *
- * When a userspace application wants to play a video, the content follows a
- * standard format definition that usually specifies the FPS for that format.
- * The below list illustrates some video format and the expected FPS,
- * respectively:
- *
- * - TV/NTSC (23.976 FPS)
- * - Cinema (24 FPS)
- * - TV/PAL (25 FPS)
- * - TV/NTSC (29.97 FPS)
- * - TV/NTSC (30 FPS)
- * - Cinema HFR (48 FPS)
- * - TV/PAL (50 FPS)
- * - Commonly used (60 FPS)
- * - Multiples of 24 (48,72,96 FPS)
- *
- * The list of standards video format is not huge and can be added to the
- * connector modeset list beforehand. With that, userspace can leverage
- * FreeSync to extends the front porch in order to attain the target refresh
- * rate. Such a switch will happen seamlessly, without screen blanking or
- * reprogramming of the output in any other way. If the userspace requests a
- * modesetting change compatible with FreeSync modes that only differ in the
- * refresh rate, DC will skip the full update and avoid blink during the
- * transition. For example, the video player can change the modesetting from
- * 60Hz to 30Hz for playing TV/NTSC content when it goes full screen without
- * causing any display blink. This same concept can be applied to a mode
- * setting change.
- */
- static struct drm_display_mode *
- get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
- bool use_probed_modes)
- {
- struct drm_display_mode *m, *m_pref = NULL;
- u16 current_refresh, highest_refresh;
- struct list_head *list_head = use_probed_modes ?
- &aconnector->base.probed_modes :
- &aconnector->base.modes;
-
- if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- return NULL;
-
- if (aconnector->freesync_vid_base.clock != 0)
- return &aconnector->freesync_vid_base;
-
- /* Find the preferred mode */
- list_for_each_entry(m, list_head, head) {
- if (m->type & DRM_MODE_TYPE_PREFERRED) {
- m_pref = m;
- break;
- }
- }
-
- if (!m_pref) {
- /* Probably an EDID with no preferred mode. Fallback to first entry */
- m_pref = list_first_entry_or_null(
- &aconnector->base.modes, struct drm_display_mode, head);
- if (!m_pref) {
- drm_dbg_driver(aconnector->base.dev, "No preferred mode found in EDID\n");
- return NULL;
- }
- }
-
- highest_refresh = drm_mode_vrefresh(m_pref);
-
- /*
- * Find the mode with highest refresh rate with same resolution.
- * For some monitors, preferred mode is not the mode with highest
- * supported refresh rate.
- */
- list_for_each_entry(m, list_head, head) {
- current_refresh = drm_mode_vrefresh(m);
-
- if (m->hdisplay == m_pref->hdisplay &&
- m->vdisplay == m_pref->vdisplay &&
- highest_refresh < current_refresh) {
- highest_refresh = current_refresh;
- m_pref = m;
- }
- }
-
- drm_mode_copy(&aconnector->freesync_vid_base, m_pref);
- return m_pref;
- }
-
- static bool is_freesync_video_mode(const struct drm_display_mode *mode,
- struct amdgpu_dm_connector *aconnector)
- {
- struct drm_display_mode *high_mode;
- int timing_diff;
-
- high_mode = get_highest_refresh_rate_mode(aconnector, false);
- if (!high_mode || !mode)
- return false;
-
- timing_diff = high_mode->vtotal - mode->vtotal;
-
- if (high_mode->clock == 0 || high_mode->clock != mode->clock ||
- high_mode->hdisplay != mode->hdisplay ||
- high_mode->vdisplay != mode->vdisplay ||
- high_mode->hsync_start != mode->hsync_start ||
- high_mode->hsync_end != mode->hsync_end ||
- high_mode->htotal != mode->htotal ||
- high_mode->hskew != mode->hskew ||
- high_mode->vscan != mode->vscan ||
- high_mode->vsync_start - mode->vsync_start != timing_diff ||
- high_mode->vsync_end - mode->vsync_end != timing_diff)
- return false;
- else
- return true;
- }
-
- #if defined(CONFIG_DRM_AMD_DC_FP)
- static void update_dsc_caps(struct amdgpu_dm_connector *aconnector,
- struct dc_sink *sink, struct dc_stream_state *stream,
- struct dsc_dec_dpcd_caps *dsc_caps)
- {
- stream->timing.flags.DSC = 0;
- dsc_caps->is_dsc_supported = false;
-
- if (aconnector->dc_link && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
- sink->sink_signal == SIGNAL_TYPE_EDP)) {
- if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE)
- dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc,
- aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
- aconnector->dc_link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
- dsc_caps);
- else if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
- if (aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT &&
- !aconnector->dsc_settings.dsc_force_disable_passthrough &&
- aconnector->dc_link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0 &&
- sink->edid_caps.frl_dsc_support &&
- sink->edid_caps.max_frl_rate > 0 &&
- sink->edid_caps.frl_dsc_max_frl_rate > 0)
- dc_dsc_parse_dsc_edid(aconnector->dc_link->ctx->dc, &sink->edid_caps, dsc_caps);
- else
- dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc,
- aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
- aconnector->dc_link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
- dsc_caps);
- }
- } else if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_HDMI_FRL) {
- if (sink->edid_caps.frl_dsc_support &&
- sink->edid_caps.max_frl_rate > 0 &&
- sink->edid_caps.frl_dsc_max_frl_rate > 0)
- dc_dsc_parse_dsc_edid(aconnector->dc_link->ctx->dc, &sink->edid_caps, dsc_caps);
- }
- }
-
- static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector,
- struct dc_sink *sink, struct dc_stream_state *stream,
- struct dsc_dec_dpcd_caps *dsc_caps,
- uint32_t max_dsc_target_bpp_limit_override)
- {
- const struct dc_link_settings *verified_link_cap = NULL;
- u32 link_bw_in_kbps;
- u32 edp_min_bpp_x16, edp_max_bpp_x16;
- struct dc *dc = sink->ctx->dc;
- struct dc_dsc_bw_range bw_range = {0};
- struct dc_dsc_config dsc_cfg = {0};
- struct dc_dsc_config_options dsc_options = {0};
-
- dc_dsc_get_default_config_option(dc, &dsc_options);
- dsc_options.max_target_bpp_limit_override_x16 = max_dsc_target_bpp_limit_override * 16;
-
- verified_link_cap = dc_link_get_link_cap(stream->link);
- link_bw_in_kbps = dc_link_bandwidth_kbps(stream->link, verified_link_cap);
- edp_min_bpp_x16 = 8 * 16;
- edp_max_bpp_x16 = 8 * 16;
-
- if (edp_max_bpp_x16 > dsc_caps->edp_max_bits_per_pixel)
- edp_max_bpp_x16 = dsc_caps->edp_max_bits_per_pixel;
-
- if (edp_max_bpp_x16 < edp_min_bpp_x16)
- edp_min_bpp_x16 = edp_max_bpp_x16;
-
- if (dc_dsc_compute_bandwidth_range(dc->res_pool->dscs[0],
- dc->debug.dsc_min_slice_height_override,
- edp_min_bpp_x16, edp_max_bpp_x16,
- dsc_caps,
- &stream->timing,
- dc_link_get_highest_encoding_format(aconnector->dc_link),
- &bw_range)) {
-
- if (bw_range.max_kbps < link_bw_in_kbps) {
- if (dc_dsc_compute_config(dc->res_pool->dscs[0],
- dsc_caps,
- &dsc_options,
- 0,
- &stream->timing,
- dc_link_get_highest_encoding_format(aconnector->dc_link),
- &dsc_cfg)) {
- stream->timing.dsc_cfg = dsc_cfg;
- stream->timing.flags.DSC = 1;
- stream->timing.dsc_cfg.bits_per_pixel = edp_max_bpp_x16;
- }
- return;
- }
- }
-
- if (dc_dsc_compute_config(dc->res_pool->dscs[0],
- dsc_caps,
- &dsc_options,
- link_bw_in_kbps,
- &stream->timing,
- dc_link_get_highest_encoding_format(aconnector->dc_link),
- &dsc_cfg)) {
- stream->timing.dsc_cfg = dsc_cfg;
- stream->timing.flags.DSC = 1;
- }
- }
-
- static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
- struct dc_sink *sink, struct dc_stream_state *stream,
- struct dsc_dec_dpcd_caps *dsc_caps)
- {
- struct drm_connector *drm_connector = &aconnector->base;
- u32 link_bandwidth_kbps;
- struct dc *dc = sink->ctx->dc;
- const struct dc_hdmi_frl_link_settings *frl_verified_link_cap = NULL;
- u32 converter_bw_in_kbps;
- u32 sink_bw_in_kbps;
- u32 dsc_sink_bw_in_kbps;
- u32 max_supported_bw_in_kbps, timing_bw_in_kbps;
- u32 dsc_max_supported_bw_in_kbps;
- u32 max_dsc_target_bpp_limit_override =
- drm_connector->display_info.max_dsc_bpp;
- struct dc_dsc_config_options dsc_options = {0};
-
- dc_dsc_get_default_config_option(dc, &dsc_options);
- dsc_options.max_target_bpp_limit_override_x16 = max_dsc_target_bpp_limit_override * 16;
-
- link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
- dc_link_get_link_cap(aconnector->dc_link));
-
- /* Set DSC policy according to dsc_clock_en */
- dc_dsc_policy_set_enable_dsc_when_not_needed(
- aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE);
-
- if (sink->sink_signal == SIGNAL_TYPE_EDP &&
- !aconnector->dc_link->panel_config.dsc.disable_dsc_edp &&
- dc->caps.edp_dsc_support && aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE) {
-
- apply_dsc_policy_for_edp(aconnector, sink, stream, dsc_caps, max_dsc_target_bpp_limit_override);
-
- } else if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
- if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) {
- if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
- dsc_caps,
- &dsc_options,
- link_bandwidth_kbps,
- &stream->timing,
- dc_link_get_highest_encoding_format(aconnector->dc_link),
- &stream->timing.dsc_cfg)) {
- stream->timing.flags.DSC = 1;
- drm_dbg_driver(drm_connector->dev, "%s: SST_DSC [%s] DSC is selected from SST RX\n",
- __func__, drm_connector->name);
- }
- } else if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
- timing_bw_in_kbps = dc_bandwidth_in_kbps_from_timing(&stream->timing,
- dc_link_get_highest_encoding_format(aconnector->dc_link));
- converter_bw_in_kbps = aconnector->dc_link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps;
- sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(dc, sink->edid_caps.max_frl_rate);
- dsc_sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(dc, sink->edid_caps.frl_dsc_max_frl_rate);
-
- if (dsc_caps->is_frl) {
- max_supported_bw_in_kbps = min(link_bandwidth_kbps, converter_bw_in_kbps);
- max_supported_bw_in_kbps = min(max_supported_bw_in_kbps, sink_bw_in_kbps);
- dsc_max_supported_bw_in_kbps = min(max_supported_bw_in_kbps, dsc_sink_bw_in_kbps);
- } else {
- max_supported_bw_in_kbps = link_bandwidth_kbps;
- dsc_max_supported_bw_in_kbps = link_bandwidth_kbps;
- }
-
- if (timing_bw_in_kbps > max_supported_bw_in_kbps &&
- max_supported_bw_in_kbps > 0 &&
- dsc_max_supported_bw_in_kbps > 0)
- if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
- dsc_caps,
- &dsc_options,
- dsc_max_supported_bw_in_kbps,
- &stream->timing,
- dc_link_get_highest_encoding_format(aconnector->dc_link),
- &stream->timing.dsc_cfg)) {
- stream->timing.flags.DSC = 1;
- drm_dbg_driver(drm_connector->dev, "%s: SST_DSC [%s] DSC is selected from %s\n",
- __func__, drm_connector->name,
- (dsc_caps->is_frl == 1) ? "HDMI FRL RX" : "DP-HDMI PCON");
- }
- }
- }
- else if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_HDMI_FRL) {
- struct dc_dsc_policy dsc_policy = {0};
-
- frl_verified_link_cap = dc_link_get_frl_link_cap(stream->link);
- if (frl_verified_link_cap->frl_link_rate != HDMI_FRL_LINK_RATE_DISABLE &&
- aconnector->dc_link->frl_flags.force_frl_dsc) {
- dc_dsc_policy_set_enable_dsc_when_not_needed(true);
- dc_dsc_get_policy_for_timing(&stream->timing, 0, &dsc_policy, dc_link_get_highest_encoding_format(stream->link));
- }
-
- timing_bw_in_kbps = dc_bandwidth_in_kbps_from_timing(&stream->timing, DC_LINK_ENCODING_HDMI_FRL);
- link_bandwidth_kbps = dc_link_frl_bandwidth_kbps(stream->link, frl_verified_link_cap->frl_link_rate);
- dsc_sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(dc, sink->edid_caps.frl_dsc_max_frl_rate);
-
- if ((timing_bw_in_kbps > link_bandwidth_kbps && dsc_sink_bw_in_kbps > 0) ||
- (dsc_policy.enable_dsc_when_not_needed || dsc_options.force_dsc_when_not_needed)) {
- if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
- dsc_caps,
- &dsc_options,
- dsc_sink_bw_in_kbps,
- &stream->timing,
- dc_link_get_highest_encoding_format(aconnector->dc_link),
- &stream->timing.dsc_cfg)) {
- stream->timing.flags.DSC = 1;
- drm_dbg_driver(drm_connector->dev, "%s: HDMI_FRL_DSC [%s] DSC is selected from HDMI FRL RX\n",
- __func__, drm_connector->name);
- }
- }
- }
-
- /* Overwrite the stream flag if DSC is enabled through debugfs */
- if (aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE)
- stream->timing.flags.DSC = 1;
-
- if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_h)
- stream->timing.dsc_cfg.num_slices_h = aconnector->dsc_settings.dsc_num_slices_h;
-
- if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_v)
- stream->timing.dsc_cfg.num_slices_v = aconnector->dsc_settings.dsc_num_slices_v;
-
- if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel)
- stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel;
- }
- #endif
-
- static struct dc_stream_state *
- create_stream_for_sink(struct drm_connector *connector,
- const struct drm_display_mode *drm_mode,
- const struct dm_connector_state *dm_state,
- const struct dc_stream_state *old_stream,
- int requested_bpc)
- {
- struct drm_device *dev = connector->dev;
- struct amdgpu_dm_connector *aconnector = NULL;
- struct drm_display_mode *preferred_mode = NULL;
- const struct drm_connector_state *con_state = &dm_state->base;
- struct dc_stream_state *stream = NULL;
- struct drm_display_mode mode;
- struct drm_display_mode saved_mode;
- struct drm_display_mode *freesync_mode = NULL;
- bool native_mode_found = false;
- bool recalculate_timing = false;
- bool scale = dm_state->scaling != RMX_OFF;
- int mode_refresh;
- int preferred_refresh = 0;
- enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN;
- #if defined(CONFIG_DRM_AMD_DC_FP)
- struct dsc_dec_dpcd_caps dsc_caps = {0};
- #endif
- struct dc_link *link = NULL;
- struct dc_sink *sink = NULL;
-
- drm_mode_init(&mode, drm_mode);
- memset(&saved_mode, 0, sizeof(saved_mode));
-
- if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) {
- aconnector = NULL;
- aconnector = to_amdgpu_dm_connector(connector);
- link = aconnector->dc_link;
- } else {
- struct drm_writeback_connector *wbcon = NULL;
- struct amdgpu_dm_wb_connector *dm_wbcon = NULL;
-
- wbcon = drm_connector_to_writeback(connector);
- dm_wbcon = to_amdgpu_dm_wb_connector(wbcon);
- link = dm_wbcon->link;
- }
-
- if (!aconnector || !aconnector->dc_sink) {
- sink = create_fake_sink(dev, link);
- if (!sink)
- return stream;
-
- } else {
- sink = aconnector->dc_sink;
- dc_sink_retain(sink);
- }
-
- stream = dc_create_stream_for_sink(sink);
-
- if (stream == NULL) {
- drm_err(dev, "Failed to create stream for sink!\n");
- goto finish;
- }
-
- /* We leave this NULL for writeback connectors */
- stream->dm_stream_context = aconnector;
-
- stream->timing.flags.LTE_340MCSC_SCRAMBLE =
- connector->display_info.hdmi.scdc.scrambling.low_rates;
-
- list_for_each_entry(preferred_mode, &connector->modes, head) {
- /* Search for preferred mode */
- if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
- native_mode_found = true;
- break;
- }
- }
- if (!native_mode_found)
- preferred_mode = list_first_entry_or_null(
- &connector->modes,
- struct drm_display_mode,
- head);
-
- mode_refresh = drm_mode_vrefresh(&mode);
-
- if (preferred_mode == NULL) {
- /*
- * This may not be an error, the use case is when we have no
- * usermode calls to reset and set mode upon hotplug. In this
- * case, we call set mode ourselves to restore the previous mode
- * and the modelist may not be filled in time.
- */
- drm_dbg_driver(dev, "No preferred mode found\n");
- } else if (aconnector) {
- recalculate_timing = amdgpu_freesync_vid_mode &&
- is_freesync_video_mode(&mode, aconnector);
- if (recalculate_timing) {
- freesync_mode = get_highest_refresh_rate_mode(aconnector, false);
- drm_mode_copy(&saved_mode, &mode);
- saved_mode.picture_aspect_ratio = mode.picture_aspect_ratio;
- drm_mode_copy(&mode, freesync_mode);
- mode.picture_aspect_ratio = saved_mode.picture_aspect_ratio;
- } else {
- decide_crtc_timing_for_drm_display_mode(
- &mode, preferred_mode, scale);
-
- preferred_refresh = drm_mode_vrefresh(preferred_mode);
- }
- }
-
- if (recalculate_timing)
- drm_mode_set_crtcinfo(&saved_mode, 0);
-
- /*
- * If scaling is enabled and refresh rate didn't change
- * we copy the vic and polarities of the old timings
- */
- if (!scale || mode_refresh != preferred_refresh)
- fill_stream_properties_from_drm_display_mode(
- stream, &mode, connector, con_state, NULL,
- requested_bpc);
- else
- fill_stream_properties_from_drm_display_mode(
- stream, &mode, connector, con_state, old_stream,
- requested_bpc);
-
- /* The rest isn't needed for writeback connectors */
- if (!aconnector)
- goto finish;
-
- if (aconnector->timing_changed) {
- drm_dbg(aconnector->base.dev,
- "overriding timing for automated test, bpc %d, changing to %d\n",
- stream->timing.display_color_depth,
- aconnector->timing_requested->display_color_depth);
- stream->timing = *aconnector->timing_requested;
- }
-
- #if defined(CONFIG_DRM_AMD_DC_FP)
- /* SST DSC determination policy */
- update_dsc_caps(aconnector, sink, stream, &dsc_caps);
- if (aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE && dsc_caps.is_dsc_supported)
- apply_dsc_policy_for_stream(aconnector, sink, stream, &dsc_caps);
- #endif
-
- update_stream_scaling_settings(dev, &mode, dm_state, stream);
-
- fill_audio_info(
- &stream->audio_info,
- connector,
- sink);
-
- update_stream_signal(stream, sink);
-
- if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
- stream->signal == SIGNAL_TYPE_HDMI_FRL)
- mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false);
-
- if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
- stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
- stream->signal == SIGNAL_TYPE_EDP) {
- const struct dc_edid_caps *edid_caps;
- unsigned int disable_colorimetry = 0;
-
- if (aconnector->dc_sink) {
- edid_caps = &aconnector->dc_sink->edid_caps;
- disable_colorimetry = edid_caps->panel_patch.disable_colorimetry;
- }
-
- //
- // should decide stream support vsc sdp colorimetry capability
- // before building vsc info packet
- //
- stream->use_vsc_sdp_for_colorimetry = stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 &&
- stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
- !disable_colorimetry;
-
- if (stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22)
- tf = TRANSFER_FUNC_GAMMA_22;
- mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf);
- aconnector->sr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
-
- }
- finish:
- dc_sink_release(sink);
-
- return stream;
- }
-
- /**
- * amdgpu_dm_connector_poll - Poll a connector to see if it's connected to a display
- * @aconnector: DM connector to poll (owns @base drm_connector and @dc_link)
- * @force: if true, force polling even when DAC load detection was used
- *
- * Used for connectors that don't support HPD (hotplug detection) to
- * periodically check whether the connector is connected to a display.
- *
- * When connection was determined via DAC load detection, we avoid
- * re-running it on normal polls to prevent visible glitches, unless
- * @force is set.
- *
- * Return: The probed connector status (connected/disconnected/unknown).
- */
- static enum drm_connector_status
- amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
- {
- struct drm_connector *connector = &aconnector->base;
- struct drm_device *dev = connector->dev;
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct dc_link *link = aconnector->dc_link;
- enum dc_connection_type conn_type = dc_connection_none;
- enum drm_connector_status status = connector_status_disconnected;
-
- /* When we determined the connection using DAC load detection,
- * do NOT poll the connector do detect disconnect because
- * that would run DAC load detection again which can cause
- * visible visual glitches.
- *
- * Only allow to poll such a connector again when forcing.
- */
- if (!force && link->local_sink && link->type == dc_connection_analog_load)
- return connector->status;
-
- mutex_lock(&aconnector->hpd_lock);
-
- if (dc_link_detect_connection_type(aconnector->dc_link, &conn_type) &&
- conn_type != dc_connection_none) {
- mutex_lock(&adev->dm.dc_lock);
-
- /* Only call full link detection when a sink isn't created yet,
- * ie. just when the display is plugged in, otherwise we risk flickering.
- */
- if (link->local_sink ||
- dc_link_detect(link, DETECT_REASON_HPD))
- status = connector_status_connected;
-
- mutex_unlock(&adev->dm.dc_lock);
- }
-
- if (connector->status != status) {
- if (status == connector_status_disconnected) {
- if (link->local_sink)
- dc_sink_release(link->local_sink);
-
- link->local_sink = NULL;
- link->dpcd_sink_count = 0;
- link->type = dc_connection_none;
- }
-
- amdgpu_dm_update_connector_after_detect(aconnector);
- }
-
- mutex_unlock(&aconnector->hpd_lock);
- return status;
- }
-
- /**
- * amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display
- *
- * A connector is considered connected when it has a sink that is not NULL.
- * For connectors that support HPD (hotplug detection), the connection is
- * handled in the HPD interrupt.
- * For connectors that may not support HPD, such as analog connectors,
- * DRM will call this function repeatedly to poll them.
- *
- * Notes:
- * 1. This interface is NOT called in context of HPD irq.
- * 2. This interface *is called* in context of user-mode ioctl. Which
- * makes it a bad place for *any* MST-related activity.
- *
- * @connector: The DRM connector we are checking. We convert it to
- * amdgpu_dm_connector so we can read the DC link and state.
- * @force: If true, do a full detect again. This is used even when
- * a lighter check would normally be used to avoid flicker.
- *
- * Return: The connector status (connected, disconnected, or unknown).
- *
- */
- static enum drm_connector_status
- amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
- {
- struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
-
- update_subconnector_property(aconnector);
-
- if (aconnector->base.force == DRM_FORCE_ON ||
- aconnector->base.force == DRM_FORCE_ON_DIGITAL)
- return connector_status_connected;
- else if (aconnector->base.force == DRM_FORCE_OFF)
- return connector_status_disconnected;
-
- /* Poll analog connectors and only when either
- * disconnected or connected to an analog display.
- */
- if (drm_kms_helper_is_poll_worker() &&
- dc_connector_supports_analog(aconnector->dc_link->link_id.id) &&
- (!aconnector->dc_sink || aconnector->dc_sink->edid_caps.analog))
- return amdgpu_dm_connector_poll(aconnector, force);
-
- return (aconnector->dc_sink ? connector_status_connected :
- connector_status_disconnected);
- }
-
- int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
- struct drm_connector_state *connector_state,
- struct drm_property *property,
- uint64_t val)
- {
- struct drm_device *dev = connector->dev;
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct dm_connector_state *dm_old_state =
- to_dm_connector_state(connector->state);
- struct dm_connector_state *dm_new_state =
- to_dm_connector_state(connector_state);
-
- int ret = -EINVAL;
-
- if (property == dev->mode_config.scaling_mode_property) {
- enum amdgpu_rmx_type rmx_type;
-
- switch (val) {
- case DRM_MODE_SCALE_CENTER:
- rmx_type = RMX_CENTER;
- break;
- case DRM_MODE_SCALE_ASPECT:
- rmx_type = RMX_ASPECT;
- break;
- case DRM_MODE_SCALE_FULLSCREEN:
- rmx_type = RMX_FULL;
- break;
- case DRM_MODE_SCALE_NONE:
- default:
- rmx_type = RMX_OFF;
- break;
- }
-
- if (dm_old_state->scaling == rmx_type)
- return 0;
-
- dm_new_state->scaling = rmx_type;
- ret = 0;
- } else if (property == adev->mode_info.underscan_hborder_property) {
- dm_new_state->underscan_hborder = val;
- ret = 0;
- } else if (property == adev->mode_info.underscan_vborder_property) {
- dm_new_state->underscan_vborder = val;
- ret = 0;
- } else if (property == adev->mode_info.underscan_property) {
- dm_new_state->underscan_enable = val;
- ret = 0;
- } else if (property == adev->mode_info.abm_level_property) {
- switch (val) {
- case ABM_SYSFS_CONTROL:
- dm_new_state->abm_sysfs_forbidden = false;
- break;
- case ABM_LEVEL_OFF:
- dm_new_state->abm_sysfs_forbidden = true;
- dm_new_state->abm_level = ABM_LEVEL_IMMEDIATE_DISABLE;
- break;
- default:
- dm_new_state->abm_sysfs_forbidden = true;
- dm_new_state->abm_level = val;
- }
- ret = 0;
- }
-
- return ret;
- }
-
- int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
- const struct drm_connector_state *state,
- struct drm_property *property,
- uint64_t *val)
- {
- struct drm_device *dev = connector->dev;
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct dm_connector_state *dm_state =
- to_dm_connector_state(state);
- int ret = -EINVAL;
-
- if (property == dev->mode_config.scaling_mode_property) {
- switch (dm_state->scaling) {
- case RMX_CENTER:
- *val = DRM_MODE_SCALE_CENTER;
- break;
- case RMX_ASPECT:
- *val = DRM_MODE_SCALE_ASPECT;
- break;
- case RMX_FULL:
- *val = DRM_MODE_SCALE_FULLSCREEN;
- break;
- case RMX_OFF:
- default:
- *val = DRM_MODE_SCALE_NONE;
- break;
- }
- ret = 0;
- } else if (property == adev->mode_info.underscan_hborder_property) {
- *val = dm_state->underscan_hborder;
- ret = 0;
- } else if (property == adev->mode_info.underscan_vborder_property) {
- *val = dm_state->underscan_vborder;
- ret = 0;
- } else if (property == adev->mode_info.underscan_property) {
- *val = dm_state->underscan_enable;
- ret = 0;
- } else if (property == adev->mode_info.abm_level_property) {
- if (!dm_state->abm_sysfs_forbidden)
- *val = ABM_SYSFS_CONTROL;
- else
- *val = (dm_state->abm_level != ABM_LEVEL_IMMEDIATE_DISABLE) ?
- dm_state->abm_level : 0;
- ret = 0;
- }
-
- return ret;
- }
-
- /**
- * DOC: panel power savings
- *
- * The display manager allows you to set your desired **panel power savings**
- * level (between 0-4, with 0 representing off), e.g. using the following::
- *
- * # echo 3 > /sys/class/drm/card0-eDP-1/amdgpu/panel_power_savings
- *
- * Modifying this value can have implications on color accuracy, so tread
- * carefully.
- */
-
- static ssize_t panel_power_savings_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
- {
- struct drm_connector *connector = dev_get_drvdata(device);
- struct drm_device *dev = connector->dev;
- u8 val;
-
- drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- val = to_dm_connector_state(connector->state)->abm_level ==
- ABM_LEVEL_IMMEDIATE_DISABLE ? 0 :
- to_dm_connector_state(connector->state)->abm_level;
- drm_modeset_unlock(&dev->mode_config.connection_mutex);
-
- return sysfs_emit(buf, "%u\n", val);
- }
-
- static ssize_t panel_power_savings_store(struct device *device,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct drm_connector *connector = dev_get_drvdata(device);
- struct drm_device *dev = connector->dev;
- long val;
- int ret;
-
- ret = kstrtol(buf, 0, &val);
-
- if (ret)
- return ret;
-
- if (val < 0 || val > 4)
- return -EINVAL;
-
- drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- if (to_dm_connector_state(connector->state)->abm_sysfs_forbidden)
- ret = -EBUSY;
- else
- to_dm_connector_state(connector->state)->abm_level = val ?:
- ABM_LEVEL_IMMEDIATE_DISABLE;
- drm_modeset_unlock(&dev->mode_config.connection_mutex);
-
- if (ret)
- return ret;
-
- drm_kms_helper_hotplug_event(dev);
-
- return count;
- }
-
- static DEVICE_ATTR_RW(panel_power_savings);
-
- static struct attribute *amdgpu_attrs[] = {
- &dev_attr_panel_power_savings.attr,
- NULL
- };
-
- static const struct attribute_group amdgpu_group = {
- .name = "amdgpu",
- .attrs = amdgpu_attrs
- };
-
- static bool
- amdgpu_dm_should_create_sysfs(struct amdgpu_dm_connector *amdgpu_dm_connector)
- {
- if (amdgpu_dm_abm_level >= 0)
- return false;
-
- if (amdgpu_dm_connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
- return false;
-
- /* check for OLED panels */
- if (amdgpu_dm_connector->bl_idx >= 0) {
- struct drm_device *drm = amdgpu_dm_connector->base.dev;
- struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm;
- struct amdgpu_dm_backlight_caps *caps;
-
- caps = &dm->backlight_caps[amdgpu_dm_connector->bl_idx];
- if (caps->aux_support)
- return false;
- }
-
- return true;
- }
-
- static void amdgpu_dm_connector_unregister(struct drm_connector *connector)
- {
- struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
-
- if (amdgpu_dm_should_create_sysfs(amdgpu_dm_connector))
- sysfs_remove_group(&connector->kdev->kobj, &amdgpu_group);
-
- cec_notifier_conn_unregister(amdgpu_dm_connector->notifier);
- drm_dp_aux_unregister(&amdgpu_dm_connector->dm_dp_aux.aux);
- }
-
- static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
- {
- struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
- struct amdgpu_device *adev = drm_to_adev(connector->dev);
- struct amdgpu_display_manager *dm = &adev->dm;
-
- /*
- * Call only if mst_mgr was initialized before since it's not done
- * for all connector types.
- */
- if (aconnector->mst_mgr.dev)
- drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr);
-
- /* Cancel and flush any pending HDMI HPD debounce work */
- if (aconnector->hdmi_hpd_debounce_delay_ms) {
- cancel_delayed_work_sync(&aconnector->hdmi_hpd_debounce_work);
- if (aconnector->hdmi_prev_sink) {
- dc_sink_release(aconnector->hdmi_prev_sink);
- aconnector->hdmi_prev_sink = NULL;
- }
- }
-
- if (aconnector->bl_idx != -1) {
- backlight_device_unregister(dm->backlight_dev[aconnector->bl_idx]);
- dm->backlight_dev[aconnector->bl_idx] = NULL;
- }
-
- if (aconnector->dc_em_sink)
- dc_sink_release(aconnector->dc_em_sink);
- aconnector->dc_em_sink = NULL;
- if (aconnector->dc_sink)
- dc_sink_release(aconnector->dc_sink);
- aconnector->dc_sink = NULL;
-
- drm_dp_cec_unregister_connector(&aconnector->dm_dp_aux.aux);
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
- kfree(aconnector->dm_dp_aux.aux.name);
-
- kfree(connector);
- }
-
- void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
- {
- struct dm_connector_state *state =
- to_dm_connector_state(connector->state);
-
- if (connector->state)
- __drm_atomic_helper_connector_destroy_state(connector->state);
-
- kfree(state);
-
- state = kzalloc_obj(*state);
-
- if (state) {
- state->scaling = RMX_OFF;
- state->underscan_enable = false;
- state->underscan_hborder = 0;
- state->underscan_vborder = 0;
- state->base.max_requested_bpc = 8;
- state->vcpi_slots = 0;
- state->pbn = 0;
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
- if (amdgpu_dm_abm_level <= 0)
- state->abm_level = ABM_LEVEL_IMMEDIATE_DISABLE;
- else
- state->abm_level = amdgpu_dm_abm_level;
- }
-
- __drm_atomic_helper_connector_reset(connector, &state->base);
- }
- }
-
- struct drm_connector_state *
- amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)
- {
- struct dm_connector_state *state =
- to_dm_connector_state(connector->state);
-
- struct dm_connector_state *new_state =
- kmemdup(state, sizeof(*state), GFP_KERNEL);
-
- if (!new_state)
- return NULL;
-
- __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
-
- new_state->freesync_capable = state->freesync_capable;
- new_state->abm_level = state->abm_level;
- new_state->scaling = state->scaling;
- new_state->underscan_enable = state->underscan_enable;
- new_state->underscan_hborder = state->underscan_hborder;
- new_state->underscan_vborder = state->underscan_vborder;
- new_state->vcpi_slots = state->vcpi_slots;
- new_state->pbn = state->pbn;
- return &new_state->base;
- }
-
- static int
- amdgpu_dm_connector_late_register(struct drm_connector *connector)
- {
- struct amdgpu_dm_connector *amdgpu_dm_connector =
- to_amdgpu_dm_connector(connector);
- int r;
-
- if (amdgpu_dm_should_create_sysfs(amdgpu_dm_connector)) {
- r = sysfs_create_group(&connector->kdev->kobj,
- &amdgpu_group);
- if (r)
- return r;
- }
-
- amdgpu_dm_register_backlight_device(amdgpu_dm_connector);
-
- if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
- (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
- amdgpu_dm_connector->dm_dp_aux.aux.dev = connector->kdev;
- r = drm_dp_aux_register(&amdgpu_dm_connector->dm_dp_aux.aux);
- if (r)
- return r;
- }
-
- #if defined(CONFIG_DEBUG_FS)
- connector_debugfs_init(amdgpu_dm_connector);
- #endif
-
- return 0;
- }
-
- static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
- {
- struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
- struct dc_link *dc_link = aconnector->dc_link;
- struct dc_sink *dc_em_sink = aconnector->dc_em_sink;
- const struct drm_edid *drm_edid;
- struct i2c_adapter *ddc;
- struct drm_device *dev = connector->dev;
-
- if (dc_link && dc_link->aux_mode)
- ddc = &aconnector->dm_dp_aux.aux.ddc;
- else
- ddc = &aconnector->i2c->base;
-
- drm_edid = drm_edid_read_ddc(connector, ddc);
- drm_edid_connector_update(connector, drm_edid);
- if (!drm_edid) {
- drm_err(dev, "No EDID found on connector: %s.\n", connector->name);
- return;
- }
-
- aconnector->drm_edid = drm_edid;
- /* Update emulated (virtual) sink's EDID */
- if (dc_em_sink && dc_link) {
- // FIXME: Get rid of drm_edid_raw()
- const struct edid *edid = drm_edid_raw(drm_edid);
-
- memset(&dc_em_sink->edid_caps, 0, sizeof(struct dc_edid_caps));
- memmove(dc_em_sink->dc_edid.raw_edid, edid,
- (edid->extensions + 1) * EDID_LENGTH);
- dm_helpers_parse_edid_caps(
- dc_link,
- &dc_em_sink->dc_edid,
- &dc_em_sink->edid_caps);
- }
- }
-
- static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
- .reset = amdgpu_dm_connector_funcs_reset,
- .detect = amdgpu_dm_connector_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = amdgpu_dm_connector_destroy,
- .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
- .atomic_set_property = amdgpu_dm_connector_atomic_set_property,
- .atomic_get_property = amdgpu_dm_connector_atomic_get_property,
- .late_register = amdgpu_dm_connector_late_register,
- .early_unregister = amdgpu_dm_connector_unregister,
- .force = amdgpu_dm_connector_funcs_force
- };
-
- static int get_modes(struct drm_connector *connector)
- {
- return amdgpu_dm_connector_get_modes(connector);
- }
-
- static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
- {
- struct drm_connector *connector = &aconnector->base;
- struct dc_link *dc_link = aconnector->dc_link;
- struct dc_sink_init_data init_params = {
- .link = aconnector->dc_link,
- .sink_signal = SIGNAL_TYPE_VIRTUAL
- };
- const struct drm_edid *drm_edid;
- const struct edid *edid;
- struct i2c_adapter *ddc;
-
- if (dc_link && dc_link->aux_mode)
- ddc = &aconnector->dm_dp_aux.aux.ddc;
- else
- ddc = &aconnector->i2c->base;
-
- drm_edid = drm_edid_read_ddc(connector, ddc);
- drm_edid_connector_update(connector, drm_edid);
- if (!drm_edid) {
- drm_err(connector->dev, "No EDID found on connector: %s.\n", connector->name);
- return;
- }
-
- if (connector->display_info.is_hdmi)
- init_params.sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;
-
- aconnector->drm_edid = drm_edid;
-
- edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw()
- aconnector->dc_em_sink = dc_link_add_remote_sink(
- aconnector->dc_link,
- (uint8_t *)edid,
- (edid->extensions + 1) * EDID_LENGTH,
- &init_params);
-
- if (aconnector->base.force == DRM_FORCE_ON) {
- aconnector->dc_sink = aconnector->dc_link->local_sink ?
- aconnector->dc_link->local_sink :
- aconnector->dc_em_sink;
- if (aconnector->dc_sink)
- dc_sink_retain(aconnector->dc_sink);
- }
- }
-
- static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
- {
- struct dc_link *link = (struct dc_link *)aconnector->dc_link;
-
- /*
- * In case of headless boot with force on for DP managed connector
- * Those settings have to be != 0 to get initial modeset
- */
- if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) {
- link->verified_link_cap.lane_count = LANE_COUNT_FOUR;
- link->verified_link_cap.link_rate = LINK_RATE_HIGH2;
- }
-
- create_eml_sink(aconnector);
- }
-
- static enum dc_status dm_validate_stream_and_context(struct dc *dc,
- struct dc_stream_state *stream)
- {
- enum dc_status dc_result = DC_ERROR_UNEXPECTED;
- struct dc_plane_state *dc_plane_state = NULL;
- struct dc_state *dc_state = NULL;
-
- if (!stream)
- goto cleanup;
-
- dc_plane_state = dc_create_plane_state(dc);
- if (!dc_plane_state)
- goto cleanup;
-
- dc_state = dc_state_create(dc, NULL);
- if (!dc_state)
- goto cleanup;
-
- /* populate stream to plane */
- dc_plane_state->src_rect.height = stream->src.height;
- dc_plane_state->src_rect.width = stream->src.width;
- dc_plane_state->dst_rect.height = stream->src.height;
- dc_plane_state->dst_rect.width = stream->src.width;
- dc_plane_state->clip_rect.height = stream->src.height;
- dc_plane_state->clip_rect.width = stream->src.width;
- dc_plane_state->plane_size.surface_pitch = ((stream->src.width + 255) / 256) * 256;
- dc_plane_state->plane_size.surface_size.height = stream->src.height;
- dc_plane_state->plane_size.surface_size.width = stream->src.width;
- dc_plane_state->plane_size.chroma_size.height = stream->src.height;
- dc_plane_state->plane_size.chroma_size.width = stream->src.width;
- dc_plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
- dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN;
- dc_plane_state->rotation = ROTATION_ANGLE_0;
- dc_plane_state->is_tiling_rotated = false;
- dc_plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_LINEAR_GENERAL;
-
- dc_result = dc_validate_stream(dc, stream);
- if (dc_result == DC_OK)
- dc_result = dc_validate_plane(dc, dc_plane_state);
-
- if (dc_result == DC_OK)
- dc_result = dc_state_add_stream(dc, dc_state, stream);
-
- if (dc_result == DC_OK && !dc_state_add_plane(
- dc,
- stream,
- dc_plane_state,
- dc_state))
- dc_result = DC_FAIL_ATTACH_SURFACES;
-
- if (dc_result == DC_OK)
- dc_result = dc_validate_global_state(dc, dc_state, DC_VALIDATE_MODE_ONLY);
-
- cleanup:
- if (dc_state)
- dc_state_release(dc_state);
-
- if (dc_plane_state)
- dc_plane_state_release(dc_plane_state);
-
- return dc_result;
- }
-
- struct dc_stream_state *
- create_validate_stream_for_sink(struct drm_connector *connector,
- const struct drm_display_mode *drm_mode,
- const struct dm_connector_state *dm_state,
- const struct dc_stream_state *old_stream)
- {
- struct amdgpu_dm_connector *aconnector = NULL;
- struct amdgpu_device *adev = drm_to_adev(connector->dev);
- struct dc_stream_state *stream;
- const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL;
- int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8;
- enum dc_status dc_result = DC_OK;
- uint8_t bpc_limit = 6;
-
- if (!dm_state)
- return NULL;
-
- if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
- aconnector = to_amdgpu_dm_connector(connector);
-
- if (aconnector &&
- (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
- aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_FRL ||
- aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER))
- bpc_limit = 8;
-
- do {
- drm_dbg_kms(connector->dev, "Trying with %d bpc\n", requested_bpc);
- stream = create_stream_for_sink(connector, drm_mode,
- dm_state, old_stream,
- requested_bpc);
- if (stream == NULL) {
- drm_err(adev_to_drm(adev), "Failed to create stream for sink!\n");
- break;
- }
-
- dc_result = dc_validate_stream(adev->dm.dc, stream);
-
- if (!aconnector) /* writeback connector */
- return stream;
-
- if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
- dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream);
-
- if (dc_result == DC_OK)
- dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);
-
- if (dc_result != DC_OK) {
- drm_dbg_kms(connector->dev, "Pruned mode %d x %d (clk %d) %s %s -- %s\n",
- drm_mode->hdisplay,
- drm_mode->vdisplay,
- drm_mode->clock,
- dc_pixel_encoding_to_str(stream->timing.pixel_encoding),
- dc_color_depth_to_str(stream->timing.display_color_depth),
- dc_status_to_str(dc_result));
-
- dc_stream_release(stream);
- stream = NULL;
- requested_bpc -= 2; /* lower bpc to retry validation */
- }
-
- } while (stream == NULL && requested_bpc >= bpc_limit);
-
- switch (dc_result) {
- /*
- * If we failed to validate DP bandwidth stream with the requested RGB color depth,
- * we try to fallback and configure in order:
- * YUV422 (8bpc, 6bpc)
- * YUV420 (8bpc, 6bpc)
- */
- case DC_FAIL_ENC_VALIDATE:
- case DC_EXCEED_DONGLE_CAP:
- case DC_NO_DP_LINK_BANDWIDTH:
- /* recursively entered twice and already tried both YUV422 and YUV420 */
- if (aconnector->force_yuv422_output && aconnector->force_yuv420_output)
- break;
- /* first failure; try YUV422 */
- if (!aconnector->force_yuv422_output) {
- drm_dbg_kms(connector->dev, "%s:%d Validation failed with %d, retrying w/ YUV422\n",
- __func__, __LINE__, dc_result);
- aconnector->force_yuv422_output = true;
- /* recursively entered and YUV422 failed, try YUV420 */
- } else if (!aconnector->force_yuv420_output) {
- drm_dbg_kms(connector->dev, "%s:%d Validation failed with %d, retrying w/ YUV420\n",
- __func__, __LINE__, dc_result);
- aconnector->force_yuv420_output = true;
- }
- stream = create_validate_stream_for_sink(connector, drm_mode,
- dm_state, old_stream);
- aconnector->force_yuv422_output = false;
- aconnector->force_yuv420_output = false;
- break;
- case DC_OK:
- break;
- default:
- drm_dbg_kms(connector->dev, "%s:%d Unhandled validation failure %d\n",
- __func__, __LINE__, dc_result);
- break;
- }
-
- return stream;
- }
-
- enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connector,
- const struct drm_display_mode *mode)
- {
- int result = MODE_ERROR;
- struct dc_sink *dc_sink;
- struct drm_display_mode *test_mode;
- /* TODO: Unhardcode stream count */
- struct dc_stream_state *stream;
- /* we always have an amdgpu_dm_connector here since we got
- * here via the amdgpu_dm_connector_helper_funcs
- */
- struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
-
- if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
- (mode->flags & DRM_MODE_FLAG_DBLSCAN))
- return result;
-
- /*
- * Only run this the first time mode_valid is called to initilialize
- * EDID mgmt
- */
- if (aconnector->base.force != DRM_FORCE_UNSPECIFIED &&
- !aconnector->dc_em_sink)
- handle_edid_mgmt(aconnector);
-
- dc_sink = to_amdgpu_dm_connector(connector)->dc_sink;
-
- if (dc_sink == NULL && aconnector->base.force != DRM_FORCE_ON_DIGITAL &&
- aconnector->base.force != DRM_FORCE_ON) {
- drm_err(connector->dev, "dc_sink is NULL!\n");
- goto fail;
- }
-
- test_mode = drm_mode_duplicate(connector->dev, mode);
- if (!test_mode)
- goto fail;
-
- drm_mode_set_crtcinfo(test_mode, 0);
-
- stream = create_validate_stream_for_sink(connector, test_mode,
- to_dm_connector_state(connector->state),
- NULL);
- drm_mode_destroy(connector->dev, test_mode);
- if (stream) {
- dc_stream_release(stream);
- result = MODE_OK;
- }
-
- fail:
- /* TODO: error handling*/
- return result;
- }
-
- static int fill_hdr_info_packet(const struct drm_connector_state *state,
- struct dc_info_packet *out)
- {
- struct hdmi_drm_infoframe frame;
- unsigned char buf[30]; /* 26 + 4 */
- ssize_t len;
- int ret, i;
-
- memset(out, 0, sizeof(*out));
-
- if (!state->hdr_output_metadata)
- return 0;
-
- ret = drm_hdmi_infoframe_set_hdr_metadata(&frame, state);
- if (ret)
- return ret;
-
- len = hdmi_drm_infoframe_pack_only(&frame, buf, sizeof(buf));
- if (len < 0)
- return (int)len;
-
- /* Static metadata is a fixed 26 bytes + 4 byte header. */
- if (len != 30)
- return -EINVAL;
-
- /* Prepare the infopacket for DC. */
- switch (state->connector->connector_type) {
- case DRM_MODE_CONNECTOR_HDMIA:
- out->hb0 = 0x87; /* type */
- out->hb1 = 0x01; /* version */
- out->hb2 = 0x1A; /* length */
- out->sb[0] = buf[3]; /* checksum */
- i = 1;
- break;
-
- case DRM_MODE_CONNECTOR_DisplayPort:
- case DRM_MODE_CONNECTOR_eDP:
- out->hb0 = 0x00; /* sdp id, zero */
- out->hb1 = 0x87; /* type */
- out->hb2 = 0x1D; /* payload len - 1 */
- out->hb3 = (0x13 << 2); /* sdp version */
- out->sb[0] = 0x01; /* version */
- out->sb[1] = 0x1A; /* length */
- i = 2;
- break;
-
- default:
- return -EINVAL;
- }
-
- memcpy(&out->sb[i], &buf[4], 26);
- out->valid = true;
-
- print_hex_dump(KERN_DEBUG, "HDR SB:", DUMP_PREFIX_NONE, 16, 1, out->sb,
- sizeof(out->sb), false);
-
- return 0;
- }
-
- static int
- amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
- struct drm_atomic_commit *state)
- {
- struct drm_connector_state *new_con_state =
- drm_atomic_get_new_connector_state(state, conn);
- struct drm_connector_state *old_con_state =
- drm_atomic_get_old_connector_state(state, conn);
- struct drm_crtc *crtc = new_con_state->crtc;
- struct drm_crtc_state *new_crtc_state;
- struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn);
- int ret;
-
- if (WARN_ON(unlikely(!old_con_state || !new_con_state)))
- return -EINVAL;
-
- trace_amdgpu_dm_connector_atomic_check(new_con_state);
-
- if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
- ret = drm_dp_mst_root_conn_atomic_check(new_con_state, &aconn->mst_mgr);
- if (ret < 0)
- return ret;
- }
-
- if (!crtc)
- return 0;
-
- if (new_con_state->privacy_screen_sw_state != old_con_state->privacy_screen_sw_state) {
- new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(new_crtc_state))
- return PTR_ERR(new_crtc_state);
-
- new_crtc_state->mode_changed = true;
- }
-
- if (new_con_state->colorspace != old_con_state->colorspace) {
- new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(new_crtc_state))
- return PTR_ERR(new_crtc_state);
-
- new_crtc_state->mode_changed = true;
- }
-
- if (new_con_state->content_type != old_con_state->content_type) {
- new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(new_crtc_state))
- return PTR_ERR(new_crtc_state);
-
- new_crtc_state->mode_changed = true;
- }
-
- if (!drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state)) {
- struct dc_info_packet hdr_infopacket;
-
- ret = fill_hdr_info_packet(new_con_state, &hdr_infopacket);
- if (ret)
- return ret;
-
- new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(new_crtc_state))
- return PTR_ERR(new_crtc_state);
-
- /*
- * DC considers the stream backends changed if the
- * static metadata changes. Forcing the modeset also
- * gives a simple way for userspace to switch from
- * 8bpc to 10bpc when setting the metadata to enter
- * or exit HDR.
- *
- * Changing the static metadata after it's been
- * set is permissible, however. So only force a
- * modeset if we're entering or exiting HDR.
- */
- new_crtc_state->mode_changed = new_crtc_state->mode_changed ||
- !old_con_state->hdr_output_metadata ||
- !new_con_state->hdr_output_metadata;
- }
-
- return 0;
- }
-
- static const struct drm_connector_helper_funcs
- amdgpu_dm_connector_helper_funcs = {
- /*
- * If hotplugging a second bigger display in FB Con mode, bigger resolution
- * modes will be filtered by drm_mode_validate_size(), and those modes
- * are missing after user start lightdm. So we need to renew modes list.
- * in get_modes call back, not just return the modes count
- */
- .get_modes = get_modes,
- .mode_valid = amdgpu_dm_connector_mode_valid,
- .atomic_check = amdgpu_dm_connector_atomic_check,
- };
-
- static void dm_encoder_helper_disable(struct drm_encoder *encoder)
- {
-
- }
-
- int convert_dc_color_depth_into_bpc(enum dc_color_depth display_color_depth)
- {
- switch (display_color_depth) {
- case COLOR_DEPTH_666:
- return 6;
- case COLOR_DEPTH_888:
- return 8;
- case COLOR_DEPTH_101010:
- return 10;
- case COLOR_DEPTH_121212:
- return 12;
- case COLOR_DEPTH_141414:
- return 14;
- case COLOR_DEPTH_161616:
- return 16;
- default:
- break;
- }
- return 0;
- }
-
- static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
- {
- struct drm_atomic_commit *state = crtc_state->state;
- struct drm_connector *connector = conn_state->connector;
- struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
- struct dm_connector_state *dm_new_connector_state = to_dm_connector_state(conn_state);
- const struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
- struct drm_dp_mst_topology_mgr *mst_mgr;
- struct drm_dp_mst_port *mst_port;
- struct drm_dp_mst_topology_state *mst_state;
- enum dc_color_depth color_depth;
- int clock, bpp = 0;
- bool is_y420 = false;
-
- if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
- (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
- struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
- struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
- enum drm_mode_status result;
-
- result = drm_crtc_helper_mode_valid_fixed(encoder->crtc, adjusted_mode, native_mode);
- if (result != MODE_OK && dm_new_connector_state->scaling == RMX_OFF) {
- drm_dbg_driver(encoder->dev,
- "mode %dx%d@%dHz is not native, enabling scaling\n",
- adjusted_mode->hdisplay, adjusted_mode->vdisplay,
- drm_mode_vrefresh(adjusted_mode));
- dm_new_connector_state->scaling = RMX_ASPECT;
- }
- return 0;
- }
-
- if (!aconnector->mst_output_port)
- return 0;
-
- mst_port = aconnector->mst_output_port;
- mst_mgr = &aconnector->mst_root->mst_mgr;
-
- if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
- return 0;
-
- mst_state = drm_atomic_get_mst_topology_state(state, mst_mgr);
- if (IS_ERR(mst_state))
- return PTR_ERR(mst_state);
-
- mst_state->pbn_div.full = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);
-
- if (!state->duplicated) {
- int max_bpc = conn_state->max_requested_bpc;
-
- is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
- aconnector->force_yuv420_output;
- color_depth = convert_color_depth_from_display_info(connector,
- is_y420,
- max_bpc);
- bpp = convert_dc_color_depth_into_bpc(color_depth) * 3;
- clock = adjusted_mode->clock;
- dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp << 4);
- }
-
- dm_new_connector_state->vcpi_slots =
- drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port,
- dm_new_connector_state->pbn);
- if (dm_new_connector_state->vcpi_slots < 0) {
- drm_dbg_atomic(connector->dev, "failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots);
- return dm_new_connector_state->vcpi_slots;
- }
- return 0;
- }
-
- const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = {
- .disable = dm_encoder_helper_disable,
- .atomic_check = dm_encoder_helper_atomic_check
- };
-
static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_commit *state,
struct dc_state *dc_state,
struct dsc_mst_fairness_vars *vars)
@@@ -8908,753 -3526,6 +3526,6 @@@
return 0;
}
- static int to_drm_connector_type(enum signal_type st, uint32_t connector_id)
- {
- switch (st) {
- case SIGNAL_TYPE_HDMI_TYPE_A:
- return DRM_MODE_CONNECTOR_HDMIA;
- case SIGNAL_TYPE_EDP:
- return DRM_MODE_CONNECTOR_eDP;
- case SIGNAL_TYPE_LVDS:
- return DRM_MODE_CONNECTOR_LVDS;
- case SIGNAL_TYPE_RGB:
- return DRM_MODE_CONNECTOR_VGA;
- case SIGNAL_TYPE_DISPLAY_PORT:
- case SIGNAL_TYPE_DISPLAY_PORT_MST:
- /* External DP bridges have a different connector type. */
- if (connector_id == CONNECTOR_ID_VGA)
- return DRM_MODE_CONNECTOR_VGA;
- else if (connector_id == CONNECTOR_ID_LVDS)
- return DRM_MODE_CONNECTOR_LVDS;
-
- return DRM_MODE_CONNECTOR_DisplayPort;
- case SIGNAL_TYPE_DVI_DUAL_LINK:
- case SIGNAL_TYPE_DVI_SINGLE_LINK:
- if (connector_id == CONNECTOR_ID_SINGLE_LINK_DVII ||
- connector_id == CONNECTOR_ID_DUAL_LINK_DVII)
- return DRM_MODE_CONNECTOR_DVII;
-
- return DRM_MODE_CONNECTOR_DVID;
- case SIGNAL_TYPE_VIRTUAL:
- return DRM_MODE_CONNECTOR_VIRTUAL;
-
- default:
- return DRM_MODE_CONNECTOR_Unknown;
- }
- }
-
- static struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *connector)
- {
- struct drm_encoder *encoder;
-
- /* There is only one encoder per connector */
- drm_connector_for_each_possible_encoder(connector, encoder)
- return encoder;
-
- return NULL;
- }
-
- static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
- {
- struct drm_encoder *encoder;
- struct amdgpu_encoder *amdgpu_encoder;
-
- encoder = amdgpu_dm_connector_to_encoder(connector);
-
- if (encoder == NULL)
- return;
-
- amdgpu_encoder = to_amdgpu_encoder(encoder);
-
- amdgpu_encoder->native_mode.clock = 0;
-
- if (!list_empty(&connector->probed_modes)) {
- struct drm_display_mode *preferred_mode = NULL;
-
- list_for_each_entry(preferred_mode,
- &connector->probed_modes,
- head) {
- if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED)
- amdgpu_encoder->native_mode = *preferred_mode;
-
- break;
- }
-
- }
- }
-
- static struct drm_display_mode *
- amdgpu_dm_create_common_mode(struct drm_encoder *encoder,
- const char *name,
- int hdisplay, int vdisplay)
- {
- struct drm_device *dev = encoder->dev;
- struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
- struct drm_display_mode *mode = NULL;
- struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
-
- mode = drm_mode_duplicate(dev, native_mode);
-
- if (mode == NULL)
- return NULL;
-
- mode->hdisplay = hdisplay;
- mode->vdisplay = vdisplay;
- mode->type &= ~DRM_MODE_TYPE_PREFERRED;
- strscpy(mode->name, name, DRM_DISPLAY_MODE_LEN);
-
- return mode;
-
- }
-
- static const struct amdgpu_dm_mode_size {
- char name[DRM_DISPLAY_MODE_LEN];
- int w;
- int h;
- } common_modes[] = {
- { "640x480", 640, 480},
- { "800x600", 800, 600},
- { "1024x768", 1024, 768},
- { "1280x720", 1280, 720},
- { "1280x800", 1280, 800},
- {"1280x1024", 1280, 1024},
- { "1440x900", 1440, 900},
- {"1680x1050", 1680, 1050},
- {"1600x1200", 1600, 1200},
- {"1920x1080", 1920, 1080},
- {"1920x1200", 1920, 1200}
- };
-
- static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
- struct drm_connector *connector)
- {
- struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
- struct drm_display_mode *mode = NULL;
- struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
- struct amdgpu_dm_connector *amdgpu_dm_connector =
- to_amdgpu_dm_connector(connector);
- int i;
- int n;
-
- if ((connector->connector_type != DRM_MODE_CONNECTOR_eDP) &&
- (connector->connector_type != DRM_MODE_CONNECTOR_LVDS))
- return;
-
- n = ARRAY_SIZE(common_modes);
-
- for (i = 0; i < n; i++) {
- struct drm_display_mode *curmode = NULL;
- bool mode_existed = false;
-
- if (common_modes[i].w > native_mode->hdisplay ||
- common_modes[i].h > native_mode->vdisplay ||
- (common_modes[i].w == native_mode->hdisplay &&
- common_modes[i].h == native_mode->vdisplay))
- continue;
-
- list_for_each_entry(curmode, &connector->probed_modes, head) {
- if (common_modes[i].w == curmode->hdisplay &&
- common_modes[i].h == curmode->vdisplay) {
- mode_existed = true;
- break;
- }
- }
-
- if (mode_existed)
- continue;
-
- mode = amdgpu_dm_create_common_mode(encoder,
- common_modes[i].name, common_modes[i].w,
- common_modes[i].h);
- if (!mode)
- continue;
-
- drm_mode_probed_add(connector, mode);
- amdgpu_dm_connector->num_modes++;
- }
- }
-
- static void amdgpu_set_panel_orientation(struct drm_connector *connector)
- {
- struct drm_encoder *encoder;
- struct amdgpu_encoder *amdgpu_encoder;
- const struct drm_display_mode *native_mode;
-
- if (connector->connector_type != DRM_MODE_CONNECTOR_eDP &&
- connector->connector_type != DRM_MODE_CONNECTOR_LVDS)
- return;
-
- mutex_lock(&connector->dev->mode_config.mutex);
- amdgpu_dm_connector_get_modes(connector);
- mutex_unlock(&connector->dev->mode_config.mutex);
-
- encoder = amdgpu_dm_connector_to_encoder(connector);
- if (!encoder)
- return;
-
- amdgpu_encoder = to_amdgpu_encoder(encoder);
-
- native_mode = &amdgpu_encoder->native_mode;
- if (native_mode->hdisplay == 0 || native_mode->vdisplay == 0)
- return;
-
- drm_connector_set_panel_orientation_with_quirk(connector,
- DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
- native_mode->hdisplay,
- native_mode->vdisplay);
- }
-
- static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
- const struct drm_edid *drm_edid)
- {
- struct amdgpu_dm_connector *amdgpu_dm_connector =
- to_amdgpu_dm_connector(connector);
-
- if (drm_edid) {
- /* empty probed_modes */
- INIT_LIST_HEAD(&connector->probed_modes);
- amdgpu_dm_connector->num_modes =
- drm_edid_connector_add_modes(connector);
-
- /* sorting the probed modes before calling function
- * amdgpu_dm_get_native_mode() since EDID can have
- * more than one preferred mode. The modes that are
- * later in the probed mode list could be of higher
- * and preferred resolution. For example, 3840x2160
- * resolution in base EDID preferred timing and 4096x2160
- * preferred resolution in DID extension block later.
- */
- drm_mode_sort(&connector->probed_modes);
- amdgpu_dm_get_native_mode(connector);
-
- /* Freesync capabilities are reset by calling
- * drm_edid_connector_add_modes() and need to be
- * restored here.
- */
- amdgpu_dm_update_freesync_caps(connector, drm_edid, false);
- } else {
- amdgpu_dm_connector->num_modes = 0;
- }
- }
-
- static bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
- struct drm_display_mode *mode)
- {
- struct drm_display_mode *m;
-
- list_for_each_entry(m, &aconnector->base.probed_modes, head) {
- if (drm_mode_equal(m, mode))
- return true;
- }
-
- return false;
- }
-
- static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
- {
- const struct drm_display_mode *m;
- struct drm_display_mode *new_mode;
- uint i;
- u32 new_modes_count = 0;
-
- /* Standard FPS values
- *
- * 23.976 - TV/NTSC
- * 24 - Cinema
- * 25 - TV/PAL
- * 29.97 - TV/NTSC
- * 30 - TV/NTSC
- * 48 - Cinema HFR
- * 50 - TV/PAL
- * 60 - Commonly used
- * 48,72,96,120 - Multiples of 24
- */
- static const u32 common_rates[] = {
- 23976, 24000, 25000, 29970, 30000,
- 48000, 50000, 60000, 72000, 96000, 120000
- };
-
- /*
- * Find mode with highest refresh rate with the same resolution
- * as the preferred mode. Some monitors report a preferred mode
- * with lower resolution than the highest refresh rate supported.
- */
-
- m = get_highest_refresh_rate_mode(aconnector, true);
- if (!m)
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(common_rates); i++) {
- u64 target_vtotal, target_vtotal_diff;
- u64 num, den;
-
- if (drm_mode_vrefresh(m) * 1000 < common_rates[i])
- continue;
-
- if (common_rates[i] < aconnector->min_vfreq * 1000 ||
- common_rates[i] > aconnector->max_vfreq * 1000)
- continue;
-
- num = (unsigned long long)m->clock * 1000 * 1000;
- den = common_rates[i] * (unsigned long long)m->htotal;
- target_vtotal = div_u64(num, den);
- target_vtotal_diff = target_vtotal - m->vtotal;
-
- /* Check for illegal modes */
- if (m->vsync_start + target_vtotal_diff < m->vdisplay ||
- m->vsync_end + target_vtotal_diff < m->vsync_start ||
- m->vtotal + target_vtotal_diff < m->vsync_end)
- continue;
-
- new_mode = drm_mode_duplicate(aconnector->base.dev, m);
- if (!new_mode)
- goto out;
-
- new_mode->vtotal += (u16)target_vtotal_diff;
- new_mode->vsync_start += (u16)target_vtotal_diff;
- new_mode->vsync_end += (u16)target_vtotal_diff;
- new_mode->type &= ~DRM_MODE_TYPE_PREFERRED;
- new_mode->type |= DRM_MODE_TYPE_DRIVER;
-
- if (!is_duplicate_mode(aconnector, new_mode)) {
- drm_mode_probed_add(&aconnector->base, new_mode);
- new_modes_count += 1;
- } else
- drm_mode_destroy(aconnector->base.dev, new_mode);
- }
- out:
- return new_modes_count;
- }
-
- static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connector,
- const struct drm_edid *drm_edid)
- {
- struct amdgpu_dm_connector *amdgpu_dm_connector =
- to_amdgpu_dm_connector(connector);
-
- if (!(amdgpu_freesync_vid_mode && drm_edid))
- return;
-
- if (!amdgpu_dm_connector->dc_sink || !amdgpu_dm_connector->dc_link)
- return;
-
- if (!dc_supports_vrr(amdgpu_dm_connector->dc_sink->ctx->dce_version))
- return;
-
- if (dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id) &&
- amdgpu_dm_connector->dc_sink->edid_caps.analog)
- return;
-
- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
- amdgpu_dm_connector->num_modes +=
- add_fs_modes(amdgpu_dm_connector);
- }
-
- static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
- {
- struct amdgpu_dm_connector *amdgpu_dm_connector =
- to_amdgpu_dm_connector(connector);
- struct dc_link *dc_link = amdgpu_dm_connector->dc_link;
- struct drm_encoder *encoder;
- const struct drm_edid *drm_edid = amdgpu_dm_connector->drm_edid;
- struct dc_link_settings *verified_link_cap = &dc_link->verified_link_cap;
- const struct dc *dc = dc_link->dc;
-
- encoder = amdgpu_dm_connector_to_encoder(connector);
-
- if (!drm_edid) {
- amdgpu_dm_connector->num_modes =
- drm_add_modes_noedid(connector, 640, 480);
- if (dc->link_srv->dp_get_encoding_format(verified_link_cap) == DP_128b_132b_ENCODING)
- amdgpu_dm_connector->num_modes +=
- drm_add_modes_noedid(connector, 1920, 1080);
-
- if (amdgpu_dm_connector->dc_sink &&
- amdgpu_dm_connector->dc_sink->edid_caps.analog &&
- dc_connector_supports_analog(dc_link->link_id.id)) {
- /* Analog monitor connected by DAC load detection.
- * Add common modes. It will be up to the user to select one that works.
- */
- for (int i = 0; i < ARRAY_SIZE(common_modes); i++)
- amdgpu_dm_connector->num_modes += drm_add_modes_noedid(
- connector, common_modes[i].w, common_modes[i].h);
- }
- } else {
- amdgpu_dm_connector_ddc_get_modes(connector, drm_edid);
- if (encoder)
- amdgpu_dm_connector_add_common_modes(encoder, connector);
- amdgpu_dm_connector_add_freesync_modes(connector, drm_edid);
- }
- amdgpu_dm_fbc_init(connector);
-
- return amdgpu_dm_connector->num_modes;
- }
-
- static const u32 supported_colorspaces =
- BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
- BIT(DRM_MODE_COLORIMETRY_OPRGB) |
- BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
- BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
-
- void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
- struct amdgpu_dm_connector *aconnector,
- int connector_type,
- struct dc_link *link,
- int link_index)
- {
- struct amdgpu_device *adev = drm_to_adev(dm->ddev);
-
- /*
- * Some of the properties below require access to state, like bpc.
- * Allocate some default initial connector state with our reset helper.
- */
- if (aconnector->base.funcs->reset)
- aconnector->base.funcs->reset(&aconnector->base);
-
- aconnector->connector_id = link_index;
- aconnector->bl_idx = -1;
- aconnector->dc_link = link;
- aconnector->base.interlace_allowed = false;
- aconnector->base.doublescan_allowed = false;
- aconnector->base.stereo_allowed = false;
- aconnector->base.dpms = DRM_MODE_DPMS_OFF;
- aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */
- aconnector->audio_inst = -1;
- aconnector->pack_sdp_v1_3 = false;
- aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE;
- memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info));
- mutex_init(&aconnector->hpd_lock);
- mutex_init(&aconnector->handle_mst_msg_ready);
-
- /*
- * If HDMI HPD debounce delay is set, use the minimum between selected
- * value and AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS
- */
- if (amdgpu_hdmi_hpd_debounce_delay_ms) {
- aconnector->hdmi_hpd_debounce_delay_ms = min(amdgpu_hdmi_hpd_debounce_delay_ms,
- AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS);
- INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work);
- aconnector->hdmi_prev_sink = NULL;
- } else {
- aconnector->hdmi_hpd_debounce_delay_ms = 0;
- }
-
- /*
- * configure support HPD hot plug connector_>polled default value is 0
- * which means HPD hot plug not supported
- */
- switch (connector_type) {
- case DRM_MODE_CONNECTOR_HDMIA:
- aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
- aconnector->base.ycbcr_420_allowed =
- link->link_enc->features.hdmi_ycbcr420_supported ? true : false;
- break;
- case DRM_MODE_CONNECTOR_DisplayPort:
- aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
- link->link_enc = link_enc_cfg_get_link_enc(link);
- ASSERT(link->link_enc);
- if (link->link_enc)
- aconnector->base.ycbcr_420_allowed =
- link->link_enc->features.dp_ycbcr420_supported ? true : false;
- break;
- case DRM_MODE_CONNECTOR_DVID:
- aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
- break;
- case DRM_MODE_CONNECTOR_DVII:
- case DRM_MODE_CONNECTOR_VGA:
- aconnector->base.polled =
- DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
- break;
- default:
- break;
- }
-
- drm_object_attach_property(&aconnector->base.base,
- dm->ddev->mode_config.scaling_mode_property,
- DRM_MODE_SCALE_NONE);
-
- if (connector_type == DRM_MODE_CONNECTOR_HDMIA
- || (connector_type == DRM_MODE_CONNECTOR_DisplayPort && !aconnector->mst_root))
- drm_connector_attach_broadcast_rgb_property(&aconnector->base);
-
- drm_object_attach_property(&aconnector->base.base,
- adev->mode_info.underscan_property,
- UNDERSCAN_OFF);
- drm_object_attach_property(&aconnector->base.base,
- adev->mode_info.underscan_hborder_property,
- 0);
- drm_object_attach_property(&aconnector->base.base,
- adev->mode_info.underscan_vborder_property,
- 0);
-
- if (!aconnector->mst_root)
- drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
-
- aconnector->base.state->max_bpc = 16;
- aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc;
-
- if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
- /* Content Type is currently only implemented for HDMI. */
- drm_connector_attach_content_type_property(&aconnector->base);
- }
-
- if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
- if (!drm_mode_create_hdmi_colorspace_property(&aconnector->base, supported_colorspaces))
- drm_connector_attach_colorspace_property(&aconnector->base);
- } else if ((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !aconnector->mst_root) ||
- connector_type == DRM_MODE_CONNECTOR_eDP) {
- if (!drm_mode_create_dp_colorspace_property(&aconnector->base, supported_colorspaces))
- drm_connector_attach_colorspace_property(&aconnector->base);
- }
-
- if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
- connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
- connector_type == DRM_MODE_CONNECTOR_eDP) {
- drm_connector_attach_hdr_output_metadata_property(&aconnector->base);
-
- if (!aconnector->mst_root)
- drm_connector_attach_vrr_capable_property(&aconnector->base);
-
- if (adev->dm.hdcp_workqueue)
- drm_connector_attach_content_protection_property(&aconnector->base, true);
- }
-
- if (connector_type == DRM_MODE_CONNECTOR_eDP) {
- struct drm_privacy_screen *privacy_screen;
-
- drm_connector_attach_panel_type_property(&aconnector->base);
-
- privacy_screen = drm_privacy_screen_get(adev_to_drm(adev)->dev, NULL);
- if (!IS_ERR(privacy_screen)) {
- drm_connector_attach_privacy_screen_provider(&aconnector->base,
- privacy_screen);
- } else if (PTR_ERR(privacy_screen) != -ENODEV) {
- drm_warn(adev_to_drm(adev), "Error getting privacy-screen\n");
- }
- }
- }
-
- static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num)
- {
- struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
- struct ddc_service *ddc_service = i2c->ddc_service;
- struct i2c_command cmd;
- int i;
- int result = -EIO;
-
- if (!ddc_service->ddc_pin)
- return result;
-
- cmd.payloads = kzalloc_objs(struct i2c_payload, num);
-
- if (!cmd.payloads)
- return result;
-
- cmd.number_of_payloads = num;
- cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;
- cmd.speed = 100;
-
- for (i = 0; i < num; i++) {
- cmd.payloads[i].write = !(msgs[i].flags & I2C_M_RD);
- cmd.payloads[i].address = msgs[i].addr;
- cmd.payloads[i].length = msgs[i].len;
- cmd.payloads[i].data = msgs[i].buf;
- }
-
- if (i2c->oem) {
- if (dc_submit_i2c_oem(
- ddc_service->ctx->dc,
- &cmd))
- result = num;
- } else {
- if (dc_submit_i2c(
- ddc_service->ctx->dc,
- ddc_service->link->link_index,
- &cmd))
- result = num;
- }
-
- kfree(cmd.payloads);
- return result;
- }
-
- static u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap)
- {
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
- }
-
- static const struct i2c_algorithm amdgpu_dm_i2c_algo = {
- .master_xfer = amdgpu_dm_i2c_xfer,
- .functionality = amdgpu_dm_i2c_func,
- };
-
- static struct amdgpu_i2c_adapter *
- create_i2c(struct ddc_service *ddc_service, bool oem)
- {
- struct amdgpu_device *adev = ddc_service->ctx->driver_context;
- struct amdgpu_i2c_adapter *i2c;
-
- i2c = kzalloc_obj(struct amdgpu_i2c_adapter);
- if (!i2c)
- return NULL;
- i2c->base.owner = THIS_MODULE;
- i2c->base.dev.parent = &adev->pdev->dev;
- i2c->base.algo = &amdgpu_dm_i2c_algo;
- if (oem)
- snprintf(i2c->base.name, sizeof(i2c->base.name), "AMDGPU DM i2c OEM bus");
- else
- snprintf(i2c->base.name, sizeof(i2c->base.name), "AMDGPU DM i2c hw bus %d",
- ddc_service->link->link_index);
- i2c_set_adapdata(&i2c->base, i2c);
- i2c->ddc_service = ddc_service;
- i2c->oem = oem;
-
- return i2c;
- }
-
- int amdgpu_dm_initialize_hdmi_connector(struct amdgpu_dm_connector *aconnector)
- {
- struct cec_connector_info conn_info;
- struct drm_device *ddev = aconnector->base.dev;
- struct device *hdmi_dev = ddev->dev;
-
- if (amdgpu_dc_debug_mask & DC_DISABLE_HDMI_CEC) {
- drm_info(ddev, "HDMI-CEC feature masked\n");
- return -EINVAL;
- }
-
- cec_fill_conn_info_from_drm(&conn_info, &aconnector->base);
- aconnector->notifier =
- cec_notifier_conn_register(hdmi_dev, NULL, &conn_info);
- if (!aconnector->notifier) {
- drm_err(ddev, "Failed to create cec notifier\n");
- return -ENOMEM;
- }
-
- return 0;
- }
-
- /*
- * Note: this function assumes that dc_link_detect() was called for the
- * dc_link which will be represented by this aconnector.
- */
- static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
- struct amdgpu_dm_connector *aconnector,
- u32 link_index,
- struct amdgpu_encoder *aencoder)
- {
- int res = 0;
- int connector_type;
- struct dc *dc = dm->dc;
- struct dc_link *link = dc_get_link_at_index(dc, link_index);
- struct amdgpu_i2c_adapter *i2c;
-
- /* Not needed for writeback connector */
- link->priv = aconnector;
-
-
- i2c = create_i2c(link->ddc, false);
- if (!i2c) {
- drm_err(adev_to_drm(dm->adev), "Failed to create i2c adapter data\n");
- return -ENOMEM;
- }
-
- aconnector->i2c = i2c;
- res = devm_i2c_add_adapter(dm->adev->dev, &i2c->base);
-
- if (res) {
- drm_err(adev_to_drm(dm->adev), "Failed to register hw i2c %d\n", link->link_index);
- goto out_free;
- }
-
- connector_type = to_drm_connector_type(link->connector_signal, link->link_id.id);
-
- res = drm_connector_init_with_ddc(
- dm->ddev,
- &aconnector->base,
- &amdgpu_dm_connector_funcs,
- connector_type,
- &i2c->base);
-
- if (res) {
- drm_err(adev_to_drm(dm->adev), "connector_init failed\n");
- aconnector->connector_id = -1;
- goto out_free;
- }
-
- drm_connector_helper_add(
- &aconnector->base,
- &amdgpu_dm_connector_helper_funcs);
-
- amdgpu_dm_connector_init_helper(
- dm,
- aconnector,
- connector_type,
- link,
- link_index);
-
- drm_connector_attach_encoder(
- &aconnector->base, &aencoder->base);
-
- if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
- connector_type == DRM_MODE_CONNECTOR_HDMIB)
- amdgpu_dm_initialize_hdmi_connector(aconnector);
-
- if (dc_is_dp_signal(link->connector_signal))
- amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index);
-
- out_free:
- if (res) {
- kfree(i2c);
- aconnector->i2c = NULL;
- }
- return res;
- }
-
- int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev)
- {
- switch (adev->mode_info.num_crtc) {
- case 1:
- return 0x1;
- case 2:
- return 0x3;
- case 3:
- return 0x7;
- case 4:
- return 0xf;
- case 5:
- return 0x1f;
- case 6:
- default:
- return 0x3f;
- }
- }
-
- static int amdgpu_dm_encoder_init(struct drm_device *dev,
- struct amdgpu_encoder *aencoder,
- uint32_t link_index)
- {
- struct amdgpu_device *adev = drm_to_adev(dev);
-
- int res = drm_encoder_init(dev,
- &aencoder->base,
- &amdgpu_dm_encoder_funcs,
- DRM_MODE_ENCODER_TMDS,
- NULL);
-
- aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
-
- if (!res)
- aencoder->encoder_id = link_index;
- else
- aencoder->encoder_id = -1;
-
- drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs);
-
- return res;
- }
-
static void manage_dm_interrupts(struct amdgpu_device *adev,
struct amdgpu_crtc *acrtc,
struct dm_crtc_state *acrtc_state)
@@@ -9754,7 -3625,7 +3625,7 @@@ static void dm_update_pflip_irq_state(s
amdgpu_irq_update(adev, &adev->pageflip_irq, irq_type);
}
- static bool
+ STATIC_IFN_KUNIT bool
is_scaling_state_different(const struct dm_connector_state *dm_state,
const struct dm_connector_state *old_dm_state)
{
@@@ -9771,6 -3642,7 +3642,7 @@@
return true;
return false;
}
+ EXPORT_IF_KUNIT(is_scaling_state_different);
static bool is_content_protection_different(struct drm_crtc_state *new_crtc_state,
struct drm_crtc_state *old_crtc_state,
@@@ -10079,7 -3951,7 +3951,7 @@@ static void amdgpu_dm_handle_vrr_transi
struct dm_crtc_state *old_state,
struct dm_crtc_state *new_state)
{
- struct amdgpu_device *adev = drm_to_adev(new_state->base.crtc->dev);
+ struct amdgpu_device *adev = dm->adev;
bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
@@@ -10384,14 -4256,12 +4256,12 @@@ static void amdgpu_dm_commit_planes(str
continue;
bundle->surface_updates[planes_count].surface = dc_plane;
- if (new_pcrtc_state->color_mgmt_changed || new_plane_state->color_mgmt_changed) {
+ if (new_pcrtc_state->color_mgmt_changed) {
bundle->surface_updates[planes_count].gamma = &dc_plane->gamma_correction;
bundle->surface_updates[planes_count].in_transfer_func = &dc_plane->in_transfer_func;
bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult;
- bundle->surface_updates[planes_count].func_shaper = &dc_plane->in_shaper_func;
- bundle->surface_updates[planes_count].lut3d_func = &dc_plane->lut3d_func;
- bundle->surface_updates[planes_count].blend_tf = &dc_plane->blend_tf;
+ bundle->surface_updates[planes_count].cm = &dc_plane->cm;
}
amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state,
@@@ -10764,87 -4634,6 +4634,6 @@@ cleanup
kfree(bundle);
}
- static void amdgpu_dm_commit_audio(struct drm_device *dev,
- struct drm_atomic_commit *state)
- {
- struct amdgpu_device *adev = drm_to_adev(dev);
- struct amdgpu_dm_connector *aconnector;
- struct drm_connector *connector;
- struct drm_connector_state *old_con_state, *new_con_state;
- struct drm_crtc_state *new_crtc_state;
- struct dm_crtc_state *new_dm_crtc_state;
- const struct dc_stream_status *status;
- int i, inst;
-
- /* Notify device removals. */
- for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
- if (old_con_state->crtc != new_con_state->crtc) {
- /* CRTC changes require notification. */
- goto notify;
- }
-
- if (!new_con_state->crtc)
- continue;
-
- new_crtc_state = drm_atomic_get_new_crtc_state(
- state, new_con_state->crtc);
-
- if (!new_crtc_state)
- continue;
-
- if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
- continue;
-
- notify:
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- continue;
-
- aconnector = to_amdgpu_dm_connector(connector);
-
- mutex_lock(&adev->dm.audio_lock);
- inst = aconnector->audio_inst;
- aconnector->audio_inst = -1;
- mutex_unlock(&adev->dm.audio_lock);
-
- amdgpu_dm_audio_eld_notify(adev, inst);
- }
-
- /* Notify audio device additions. */
- for_each_new_connector_in_state(state, connector, new_con_state, i) {
- if (!new_con_state->crtc)
- continue;
-
- new_crtc_state = drm_atomic_get_new_crtc_state(
- state, new_con_state->crtc);
-
- if (!new_crtc_state)
- continue;
-
- if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
- continue;
-
- new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
- if (!new_dm_crtc_state->stream)
- continue;
-
- status = dc_stream_get_status(new_dm_crtc_state->stream);
- if (!status)
- continue;
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- continue;
-
- aconnector = to_amdgpu_dm_connector(connector);
-
- mutex_lock(&adev->dm.audio_lock);
- inst = status->audio_inst;
- aconnector->audio_inst = inst;
- mutex_unlock(&adev->dm.audio_lock);
-
- amdgpu_dm_audio_eld_notify(adev, inst);
- }
- }
-
/*
* amdgpu_dm_crtc_copy_transient_flags - copy mirrored flags from DRM to DC
* @crtc_state: the DRM CRTC state
@@@ -10859,10 -4648,55 +4648,55 @@@ static void amdgpu_dm_crtc_copy_transie
stream_state->mode_changed = drm_atomic_crtc_needs_modeset(crtc_state);
}
+ /**
+ * amdgpu_dm_crtc_complete_writeback - finish a pending writeback job
+ * @acrtc: the CRTC whose pending writeback should be completed
+ *
+ * Clears the pending state, signals the writeback out fence and releases the
+ * vblank reference taken in dm_set_writeback() while the writeback was armed.
+ * The pending flag is tested and cleared under the writeback job lock, so this
+ * is safe to call concurrently from the completion vblank IRQ
+ * (dm_crtc_high_irq()) and from the writeback teardown path
+ * (dm_clear_writeback()); only the caller that observes the pending job
+ * performs the completion.
+ *
+ * Return: true if a pending writeback job was completed by this call.
+ */
+ bool amdgpu_dm_crtc_complete_writeback(struct amdgpu_crtc *acrtc)
+ {
+ unsigned long flags;
+ bool pending;
+
+ if (!acrtc->wb_conn)
+ return false;
+
+ spin_lock_irqsave(&acrtc->wb_conn->job_lock, flags);
+ pending = acrtc->wb_pending;
+ acrtc->wb_pending = false;
+ spin_unlock_irqrestore(&acrtc->wb_conn->job_lock, flags);
+
+ if (!pending)
+ return false;
+
+ drm_writeback_signal_completion(acrtc->wb_conn, 0);
+ drm_crtc_vblank_put(&acrtc->base);
+
+ return true;
+ }
+
static void dm_clear_writeback(struct amdgpu_display_manager *dm,
+ struct amdgpu_crtc *acrtc,
struct dm_crtc_state *crtc_state)
{
dc_stream_remove_writeback(dm->dc, crtc_state->stream, 0);
+
+ /*
+ * If the writeback is still pending when it is torn down (its
+ * completion vblank IRQ never fired), signal the out fence so a
+ * waiting client does not stall and release the vblank reference
+ * taken in dm_set_writeback().
+ */
+ amdgpu_dm_crtc_complete_writeback(acrtc);
}
/**
@@@ -11015,7 -4849,7 +4849,7 @@@ static void amdgpu_dm_commit_streams(st
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
- dm_clear_writeback(dm, dm_old_crtc_state);
+ dm_clear_writeback(dm, acrtc, dm_old_crtc_state);
acrtc->wb_enabled = false;
}
@@@ -11289,9 -5123,24 +5123,24 @@@ static void dm_set_writeback(struct amd
dc_stream_add_writeback(dm->dc, crtc_state->stream, wb_info);
- acrtc->wb_pending = true;
acrtc->wb_conn = wb_conn;
drm_writeback_queue_job(wb_conn, new_con_state);
+
+ /*
+ * Writeback completion is detected in the CRTC vblank IRQ
+ * (dm_crtc_high_irq()). Take a vblank reference so the vblank interrupt
+ * stays enabled while the writeback is pending; otherwise a
+ * writeback-only commit right after drm_crtc_vblank_on() (e.g.
+ * re-enabling a CRTC that was disabled) has no other vblank reference,
+ * the IRQ never fires and the out fence times out. The matching put
+ * happens once completion is signalled in dm_crtc_high_irq(), or when
+ * the writeback is torn down in dm_clear_writeback().
+ *
+ * Arm wb_pending only after the reference is held so the completion IRQ
+ * cannot run its matching vblank_put before this get.
+ */
+ WARN_ON(drm_crtc_vblank_get(&acrtc->base));
+ acrtc->wb_pending = true;
}
static void amdgpu_dm_update_hdcp(struct drm_atomic_commit *state)
@@@ -11442,6 -5291,74 +5291,74 @@@ static int amdgpu_dm_atomic_setup_commi
return 0;
}
+ STATIC_IFN_KUNIT void set_multisync_trigger_params(
+ struct dc_stream_state *stream)
+ {
+ struct dc_stream_state *master = NULL;
+
+ if (stream->triggered_crtc_reset.enabled) {
+ master = stream->triggered_crtc_reset.event_source;
+ stream->triggered_crtc_reset.event =
+ master->timing.flags.VSYNC_POSITIVE_POLARITY ?
+ CRTC_EVENT_VSYNC_RISING : CRTC_EVENT_VSYNC_FALLING;
+ stream->triggered_crtc_reset.delay = TRIGGER_DELAY_NEXT_PIXEL;
+ }
+ }
+ EXPORT_IF_KUNIT(set_multisync_trigger_params);
+
+ STATIC_IFN_KUNIT void set_master_stream(struct dc_stream_state *stream_set[],
+ int stream_count)
+ {
+ int j, highest_rfr = 0, master_stream = 0;
+
+ for (j = 0; j < stream_count; j++) {
+ if (stream_set[j] && stream_set[j]->triggered_crtc_reset.enabled) {
+ int refresh_rate = 0;
+
+ refresh_rate = (stream_set[j]->timing.pix_clk_100hz*100)/
+ (stream_set[j]->timing.h_total*stream_set[j]->timing.v_total);
+ if (refresh_rate > highest_rfr) {
+ highest_rfr = refresh_rate;
+ master_stream = j;
+ }
+ }
+ }
+ for (j = 0; j < stream_count; j++) {
+ if (stream_set[j])
+ stream_set[j]->triggered_crtc_reset.event_source = stream_set[master_stream];
+ }
+ }
+ EXPORT_IF_KUNIT(set_master_stream);
+
+ static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context)
+ {
+ int i = 0;
+ struct dc_stream_state *stream;
+
+ if (context->stream_count < 2)
+ return;
+ for (i = 0; i < context->stream_count ; i++) {
+ if (!context->streams[i])
+ continue;
+ /*
+ * TODO: add a function to read AMD VSDB bits and set
+ * crtc_sync_master.multi_sync_enabled flag
+ * For now it's set to false
+ */
+ }
+
+ set_master_stream(context->streams, context->stream_count);
+
+ for (i = 0; i < context->stream_count ; i++) {
+ stream = context->streams[i];
+
+ if (!stream)
+ continue;
+
+ set_multisync_trigger_params(stream);
+ }
+ }
+
/**
* amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation.
* @state: The atomic state to commit
@@@ -11510,7 -5427,7 +5427,7 @@@ static void amdgpu_dm_atomic_commit_tai
if ((new_con_state->hdmi.broadcast_rgb != old_con_state->hdmi.broadcast_rgb) &&
(dm_old_crtc_state->stream->output_color_space !=
- get_output_color_space(&dm_new_crtc_state->stream->timing, new_con_state)))
+ amdgpu_dm_get_output_color_space(&dm_new_crtc_state->stream->timing, new_con_state)))
output_color_space_changed = true;
abm_changed = dm_new_crtc_state->abm_level !=
@@@ -11524,7 -5441,7 +5441,7 @@@
stream_update.stream = dm_new_crtc_state->stream;
if (scaling_changed) {
- update_stream_scaling_settings(dev, &dm_new_con_state->base.crtc->mode,
+ amdgpu_dm_update_stream_scaling_settings(dev, &dm_new_con_state->base.crtc->mode,
dm_new_con_state, dm_new_crtc_state->stream);
stream_update.src = dm_new_crtc_state->stream->src;
@@@ -11533,7 -5450,7 +5450,7 @@@
if (output_color_space_changed) {
dm_new_crtc_state->stream->output_color_space
- = get_output_color_space(&dm_new_crtc_state->stream->timing, new_con_state);
+ = amdgpu_dm_get_output_color_space(&dm_new_crtc_state->stream->timing, new_con_state);
stream_update.output_color_space = &dm_new_crtc_state->stream->output_color_space;
}
@@@ -11545,7 -5462,7 +5462,7 @@@
}
if (hdr_changed) {
- fill_hdr_info_packet(new_con_state, &hdr_packet);
+ amdgpu_dm_fill_hdr_info_packet(new_con_state, &hdr_packet);
stream_update.hdr_static_metadata = &hdr_packet;
}
@@@ -11753,104 -5670,6 +5670,6 @@@
trace_amdgpu_dm_atomic_commit_tail_finish(state);
}
- static int dm_force_atomic_commit(struct drm_connector *connector)
- {
- int ret = 0;
- struct drm_device *ddev = connector->dev;
- struct drm_atomic_commit *state = drm_atomic_commit_alloc(ddev);
- struct amdgpu_crtc *disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc);
- struct drm_plane *plane = disconnected_acrtc->base.primary;
- struct drm_connector_state *conn_state;
- struct drm_crtc_state *crtc_state;
- struct drm_plane_state *plane_state;
-
- if (!state)
- return -ENOMEM;
-
- state->acquire_ctx = ddev->mode_config.acquire_ctx;
-
- /* Construct an atomic state to restore previous display setting */
-
- /*
- * Attach connectors to drm_atomic_commit
- */
- conn_state = drm_atomic_get_connector_state(state, connector);
-
- /* Check for error in getting connector state */
- if (IS_ERR(conn_state)) {
- ret = PTR_ERR(conn_state);
- goto out;
- }
-
- /* Attach crtc to drm_atomic_commit*/
- crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base);
-
- /* Check for error in getting crtc state */
- if (IS_ERR(crtc_state)) {
- ret = PTR_ERR(crtc_state);
- goto out;
- }
-
- /* force a restore */
- crtc_state->mode_changed = true;
-
- /* Attach plane to drm_atomic_commit */
- plane_state = drm_atomic_get_plane_state(state, plane);
-
- /* Check for error in getting plane state */
- if (IS_ERR(plane_state)) {
- ret = PTR_ERR(plane_state);
- goto out;
- }
-
- /* Call commit internally with the state we just constructed */
- ret = drm_atomic_commit(state);
-
- out:
- drm_atomic_commit_put(state);
- if (ret)
- drm_err(ddev, "Restoring old state failed with %i\n", ret);
-
- return ret;
- }
-
- /*
- * This function handles all cases when set mode does not come upon hotplug.
- * This includes when a display is unplugged then plugged back into the
- * same port and when running without usermode desktop manager supprot
- */
- void dm_restore_drm_connector_state(struct drm_device *dev,
- struct drm_connector *connector)
- {
- struct amdgpu_dm_connector *aconnector;
- struct amdgpu_crtc *disconnected_acrtc;
- struct dm_crtc_state *acrtc_state;
-
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
- return;
-
- aconnector = to_amdgpu_dm_connector(connector);
-
- if (!aconnector->dc_sink || !connector->state || !connector->encoder)
- return;
-
- disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc);
- if (!disconnected_acrtc)
- return;
-
- acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state);
- if (!acrtc_state->stream)
- return;
-
- /*
- * If the previous sink is not released and different from the current,
- * we deduce we are in a state where we can not rely on usermode call
- * to turn on the display, so we do it here
- */
- if (acrtc_state->stream->sink != aconnector->dc_sink)
- dm_force_atomic_commit(&aconnector->base);
- }
-
/*
* Grabs all modesetting locks to serialize against any blocking commits,
* Waits for completion of all non blocking commits.
@@@ -11955,7 -5774,7 +5774,7 @@@ static void reset_freesync_config_for_c
sizeof(new_crtc_state->vrr_infopacket));
}
- static bool
+ STATIC_IFN_KUNIT bool
is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
struct drm_crtc_state *new_crtc_state)
{
@@@ -11984,8 -5803,9 +5803,9 @@@
return false;
}
+ EXPORT_IF_KUNIT(is_timing_unchanged_for_freesync);
- static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
+ STATIC_IFN_KUNIT void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
{
u64 num, den, res;
struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
@@@ -11999,6 -5819,7 +5819,7 @@@
res = div_u64(num, den);
dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = res;
}
+ EXPORT_IF_KUNIT(set_freesync_fixed_config);
static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
struct drm_atomic_commit *state,
@@@ -12052,7 -5873,7 +5873,7 @@@
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
goto skip_modeset;
- new_stream = create_validate_stream_for_sink(connector,
+ new_stream = amdgpu_dm_create_validate_stream_for_sink(connector,
&new_crtc_state->mode,
dm_new_conn_state,
dm_old_crtc_state->stream);
@@@ -12080,7 -5901,7 +5901,7 @@@
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
- ret = fill_hdr_info_packet(drm_new_conn_state,
+ ret = amdgpu_dm_fill_hdr_info_packet(drm_new_conn_state,
&new_stream->hdr_static_metadata);
if (ret)
goto fail;
@@@ -12149,11 -5970,11 +5970,11 @@@
goto skip_modeset;
} else if (amdgpu_freesync_vid_mode && aconnector &&
- is_freesync_video_mode(&new_crtc_state->mode,
+ amdgpu_dm_is_freesync_video_mode(&new_crtc_state->mode,
aconnector)) {
struct drm_display_mode *high_mode;
- high_mode = get_highest_refresh_rate_mode(aconnector, false);
+ high_mode = amdgpu_dm_get_highest_refresh_rate_mode(aconnector, false);
if (!drm_mode_equal(&new_crtc_state->mode, high_mode))
set_freesync_fixed_config(dm_new_crtc_state);
}
@@@ -12246,7 -6067,7 +6067,7 @@@ skip_modeset
/* Scaling or underscan settings */
if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state) ||
drm_atomic_crtc_needs_modeset(new_crtc_state))
- update_stream_scaling_settings(adev_to_drm(adev),
+ amdgpu_dm_update_stream_scaling_settings(adev_to_drm(adev),
&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
/* ABM settings */
@@@ -12342,10 -6163,6 +6163,6 @@@ static bool should_reset_plane(struct d
if (new_crtc_state->color_mgmt_changed)
return true;
- /* Plane color pipeline or its colorop changes. */
- if (new_plane_state->color_mgmt_changed)
- return true;
-
/*
* On zpos change, planes need to be reordered by removing and re-adding
* them one by one to the dc state, in order of descending zpos.
@@@ -12720,7 -6537,7 +6537,7 @@@ static int dm_update_plane_state(struc
/* Tell DC to do a full surface update every time there
* is a plane change. Inefficient, but works for now.
*/
- dm_new_plane_state->dc_state->update_flags.bits.full_update = 1;
+ dm_new_plane_state->dc_state->update_bits.full_update = 1;
*lock_and_validation_needed = true;
}
@@@ -12739,8 -6556,8 +6556,8 @@@ out
return ret;
}
- static void dm_get_oriented_plane_size(struct drm_plane_state *plane_state,
- int *src_w, int *src_h)
+ STATIC_IFN_KUNIT void dm_get_oriented_plane_size(struct drm_plane_state *plane_state,
+ int *src_w, int *src_h)
{
switch (plane_state->rotation & DRM_MODE_ROTATE_MASK) {
case DRM_MODE_ROTATE_90:
@@@ -12756,8 -6573,9 +6573,9 @@@
break;
}
}
+ EXPORT_IF_KUNIT(dm_get_oriented_plane_size);
- static void
+ STATIC_IFN_KUNIT void
dm_get_plane_scale(struct drm_plane_state *plane_state,
int *out_plane_scale_w, int *out_plane_scale_h)
{
@@@ -12767,6 -6585,7 +6585,7 @@@
*out_plane_scale_w = plane_src_w ? plane_state->crtc_w * 1000 / plane_src_w : 0;
*out_plane_scale_h = plane_src_h ? plane_state->crtc_h * 1000 / plane_src_h : 0;
}
+ EXPORT_IF_KUNIT(dm_get_plane_scale);
/*
* The normalized_zpos value cannot be used by this iterator directly. It's only
@@@ -12986,6 -6805,31 +6805,31 @@@ static int dm_crtc_get_cursor_mode(stru
break;
}
+ /*
+ * A non-cursor plane moving or resizing (without a scale change)
+ * changes how much of the CRTC it covers. This can create or
+ * remove a hole under the cursor and thus flip the required
+ * cursor mode (native vs overlay), so its destination rect must
+ * be re-evaluated too.
+ *
+ * The cursor plane itself is deliberately excluded: the cursor
+ * mode depends on the underlying planes' coverage, not on the
+ * cursor's position (see the entire_crtc_covered logic below).
+ * Triggering on cursor movement would force every legacy cursor
+ * update off its fast path, and in a cursor-only commit - where
+ * the underlying planes are not part of the state - the coverage
+ * loop would see no covering plane and misevaluate the mode as
+ * overlay, regressing flip-vs-cursor-legacy.
+ */
+ if (plane->type != DRM_PLANE_TYPE_CURSOR &&
+ (old_plane_state->crtc_x != plane_state->crtc_x ||
+ old_plane_state->crtc_y != plane_state->crtc_y ||
+ old_plane_state->crtc_w != plane_state->crtc_w ||
+ old_plane_state->crtc_h != plane_state->crtc_h)) {
+ consider_mode_change = true;
+ break;
+ }
+
if (dm_plane_color_pipeline_active(state, plane, true) !=
dm_plane_color_pipeline_active(state, plane, false)) {
consider_mode_change = true;
@@@ -13141,7 -6985,7 +6985,7 @@@ static int amdgpu_dm_atomic_check(struc
ret = drm_atomic_helper_check_modeset(dev, state);
if (ret) {
- drm_dbg_atomic(dev, "drm_atomic_helper_check_modeset() failed\n");
+ drm_dbg_atomic(dev, "drm_atomic_helper_check_modeset() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13156,7 -7000,7 +7000,7 @@@
new_crtc_state = drm_atomic_get_crtc_state(state, new_con_state->crtc);
if (IS_ERR(new_crtc_state)) {
- drm_dbg_atomic(dev, "drm_atomic_get_crtc_state() failed\n");
+ drm_dbg_atomic(dev, "drm_atomic_get_crtc_state() failed: %pe\n", new_crtc_state);
ret = PTR_ERR(new_crtc_state);
goto fail;
}
@@@ -13176,7 -7020,7 +7020,7 @@@
if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
ret = add_affected_mst_dsc_crtcs(state, crtc);
if (ret) {
- drm_dbg_atomic(dev, "add_affected_mst_dsc_crtcs() failed\n");
+ drm_dbg_atomic(dev, "add_affected_mst_dsc_crtcs() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
}
@@@ -13193,7 -7037,7 +7037,7 @@@
ret = amdgpu_dm_verify_lut_sizes(new_crtc_state);
if (ret) {
- drm_dbg_atomic(dev, "amdgpu_dm_verify_lut_sizes() failed\n");
+ drm_dbg_atomic(dev, "amdgpu_dm_verify_lut_sizes() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13202,13 -7046,13 +7046,13 @@@
ret = drm_atomic_add_affected_connectors(state, crtc);
if (ret) {
- drm_dbg_atomic(dev, "drm_atomic_add_affected_connectors() failed\n");
+ drm_dbg_atomic(dev, "drm_atomic_add_affected_connectors() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
ret = drm_atomic_add_affected_planes(state, crtc);
if (ret) {
- drm_dbg_atomic(dev, "drm_atomic_add_affected_planes() failed\n");
+ drm_dbg_atomic(dev, "drm_atomic_add_affected_planes() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13247,7 -7091,7 +7091,7 @@@
if (IS_ERR(new_plane_state)) {
ret = PTR_ERR(new_plane_state);
- drm_dbg_atomic(dev, "new_plane_state is BAD\n");
+ drm_dbg_atomic(dev, "new_plane_state is BAD: %pe\n", new_plane_state);
goto fail;
}
}
@@@ -13261,7 -7105,7 +7105,7 @@@
*/
ret = drm_atomic_normalize_zpos(dev, state);
if (ret) {
- drm_dbg(dev, "drm_atomic_normalize_zpos() failed\n");
+ drm_dbg(dev, "drm_atomic_normalize_zpos() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13275,7 -7119,7 +7119,7 @@@
ret = dm_crtc_get_cursor_mode(adev, state, dm_new_crtc_state,
&dm_new_crtc_state->cursor_mode);
if (ret) {
- drm_dbg(dev, "Failed to determine cursor mode\n");
+ drm_dbg(dev, "Failed to determine cursor mode: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13307,7 -7151,7 +7151,7 @@@
&lock_and_validation_needed,
&is_top_most_overlay);
if (ret) {
- drm_dbg_atomic(dev, "dm_update_plane_state() failed\n");
+ drm_dbg_atomic(dev, "dm_update_plane_state() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
}
@@@ -13320,7 -7164,7 +7164,7 @@@
false,
&lock_and_validation_needed);
if (ret) {
- drm_dbg_atomic(dev, "DISABLE: dm_update_crtc_state() failed\n");
+ drm_dbg_atomic(dev, "DISABLE: dm_update_crtc_state() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
}
@@@ -13333,7 -7177,7 +7177,7 @@@
true,
&lock_and_validation_needed);
if (ret) {
- drm_dbg_atomic(dev, "ENABLE: dm_update_crtc_state() failed\n");
+ drm_dbg_atomic(dev, "ENABLE: dm_update_crtc_state() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
}
@@@ -13347,7 -7191,7 +7191,7 @@@
&lock_and_validation_needed,
&is_top_most_overlay);
if (ret) {
- drm_dbg_atomic(dev, "dm_update_plane_state() failed\n");
+ drm_dbg_atomic(dev, "dm_update_plane_state() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
}
@@@ -13363,7 -7207,7 +7207,7 @@@
/* Run this here since we want to validate the streams we created */
ret = drm_atomic_helper_check_planes(dev, state);
if (ret) {
- drm_dbg_atomic(dev, "drm_atomic_helper_check_planes() failed\n");
+ drm_dbg_atomic(dev, "drm_atomic_helper_check_planes() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13501,13 -7345,13 +7345,13 @@@
if (lock_and_validation_needed) {
ret = dm_atomic_get_state(state, &dm_state);
if (ret) {
- drm_dbg_atomic(dev, "dm_atomic_get_state() failed\n");
+ drm_dbg_atomic(dev, "dm_atomic_get_state() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
ret = do_aquire_global_lock(dev, state);
if (ret) {
- drm_dbg_atomic(dev, "do_aquire_global_lock() failed\n");
+ drm_dbg_atomic(dev, "do_aquire_global_lock() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13515,7 -7359,7 +7359,7 @@@
if (dc_resource_is_dsc_encoding_supported(dc)) {
ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
if (ret) {
- drm_dbg_atomic(dev, "MST_DSC compute_mst_dsc_configs_for_state() failed\n");
+ drm_dbg_atomic(dev, "MST_DSC compute_mst_dsc_configs_for_state() failed: %pe\n", ERR_PTR(ret));
ret = -EINVAL;
goto fail;
}
@@@ -13524,7 -7368,7 +7368,7 @@@
ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context, vars);
if (ret) {
- drm_dbg_atomic(dev, "dm_update_mst_vcpi_slots_for_dsc() failed\n");
+ drm_dbg_atomic(dev, "dm_update_mst_vcpi_slots_for_dsc() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
@@@ -13536,7 -7380,7 +7380,7 @@@
*/
ret = drm_dp_mst_atomic_check(state);
if (ret) {
- drm_dbg_atomic(dev, "MST drm_dp_mst_atomic_check() failed\n");
+ drm_dbg_atomic(dev, "MST drm_dp_mst_atomic_check() failed: %pe\n", ERR_PTR(ret));
goto fail;
}
status = dc_validate_global_state(dc, dm_state->context, DC_VALIDATE_MODE_ONLY);
@@@ -13625,380 -7469,13 +7469,13 @@@ fail
else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
drm_dbg_atomic(dev, "Atomic check stopped due to signal.\n");
else
- drm_dbg_atomic(dev, "Atomic check failed with err: %d\n", ret);
+ drm_dbg_atomic(dev, "Atomic check failed: %pe\n", ERR_PTR(ret));
trace_amdgpu_dm_atomic_check_finish(state, ret);
return ret;
}
- static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
- unsigned int offset,
- unsigned int total_length,
- u8 *data,
- unsigned int length,
- struct amdgpu_hdmi_vsdb_info *vsdb)
- {
- bool res;
- union dmub_rb_cmd cmd;
- struct dmub_cmd_send_edid_cea *input;
- struct dmub_cmd_edid_cea_output *output;
-
- if (length > DMUB_EDID_CEA_DATA_CHUNK_BYTES)
- return false;
-
- memset(&cmd, 0, sizeof(cmd));
-
- input = &cmd.edid_cea.data.input;
-
- cmd.edid_cea.header.type = DMUB_CMD__EDID_CEA;
- cmd.edid_cea.header.sub_type = 0;
- cmd.edid_cea.header.payload_bytes =
- sizeof(cmd.edid_cea) - sizeof(cmd.edid_cea.header);
- input->offset = offset;
- input->length = length;
- input->cea_total_length = total_length;
- memcpy(input->payload, data, length);
-
- res = dc_wake_and_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
- if (!res) {
- drm_err(adev_to_drm(dm->adev), "EDID CEA parser failed\n");
- return false;
- }
-
- output = &cmd.edid_cea.data.output;
-
- if (output->type == DMUB_CMD__EDID_CEA_ACK) {
- if (!output->ack.success) {
- drm_err(adev_to_drm(dm->adev), "EDID CEA ack failed at offset %d\n",
- output->ack.offset);
- }
- } else if (output->type == DMUB_CMD__EDID_CEA_AMD_VSDB) {
- if (!output->amd_vsdb.vsdb_found)
- return false;
-
- vsdb->freesync_supported = output->amd_vsdb.freesync_supported;
- vsdb->amd_vsdb_version = output->amd_vsdb.amd_vsdb_version;
- vsdb->min_refresh_rate_hz = output->amd_vsdb.min_frame_rate;
- vsdb->max_refresh_rate_hz = output->amd_vsdb.max_frame_rate;
- vsdb->freesync_mccs_vcp_code = output->amd_vsdb.freesync_mccs_vcp_code;
- } else {
- drm_warn(adev_to_drm(dm->adev), "Unknown EDID CEA parser results\n");
- return false;
- }
-
- return true;
- }
-
- static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
- u8 *edid_ext, int len,
- struct amdgpu_hdmi_vsdb_info *vsdb_info)
- {
- int i;
-
- /* send extension block to DMCU for parsing */
- for (i = 0; i < len; i += 8) {
- bool res;
- int offset;
-
- /* send 8 bytes a time */
- if (!dc_edid_parser_send_cea(dm->dc, i, len, &edid_ext[i], 8))
- return false;
-
- if (i+8 == len) {
- /* EDID block sent completed, expect result */
- int version, min_rate, max_rate;
-
- res = dc_edid_parser_recv_amd_vsdb(dm->dc, &version, &min_rate, &max_rate);
- if (res) {
- /* amd vsdb found */
- vsdb_info->freesync_supported = 1;
- vsdb_info->amd_vsdb_version = version;
- vsdb_info->min_refresh_rate_hz = min_rate;
- vsdb_info->max_refresh_rate_hz = max_rate;
- /* Not enabled on DMCU*/
- vsdb_info->freesync_mccs_vcp_code = 0;
- return true;
- }
- /* not amd vsdb */
- return false;
- }
-
- /* check for ack*/
- res = dc_edid_parser_recv_cea_ack(dm->dc, &offset);
- if (!res)
- return false;
- }
-
- return false;
- }
-
- static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
- u8 *edid_ext, int len,
- struct amdgpu_hdmi_vsdb_info *vsdb_info)
- {
- int i;
-
- /* send extension block to DMCU for parsing */
- for (i = 0; i < len; i += 8) {
- /* send 8 bytes a time */
- if (!dm_edid_parser_send_cea(dm, i, len, &edid_ext[i], 8, vsdb_info))
- return false;
- }
-
- return vsdb_info->freesync_supported;
- }
-
- static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
- u8 *edid_ext, int len,
- struct amdgpu_hdmi_vsdb_info *vsdb_info)
- {
- struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
- bool ret;
-
- mutex_lock(&adev->dm.dc_lock);
- if (adev->dm.dmub_srv)
- ret = parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
- else
- ret = parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
- mutex_unlock(&adev->dm.dc_lock);
- return ret;
- }
-
- static void parse_edid_displayid_vrr(struct drm_connector *connector,
- const struct edid *edid)
- {
- u8 *edid_ext = NULL;
- int i;
- int j = 0;
- u16 min_vfreq;
- u16 max_vfreq;
-
- if (!edid || !edid->extensions)
- return;
-
- /* Find DisplayID extension */
- for (i = 0; i < edid->extensions; i++) {
- edid_ext = (void *)(edid + (i + 1));
- if (edid_ext[0] == DISPLAYID_EXT)
- break;
- }
-
- if (i == edid->extensions)
- return;
-
- while (j < EDID_LENGTH) {
- /* Get dynamic video timing range from DisplayID if available */
- if (EDID_LENGTH - j > 13 && edid_ext[j] == 0x25 &&
- (edid_ext[j+1] & 0xFE) == 0 && (edid_ext[j+2] == 9)) {
- min_vfreq = edid_ext[j+9];
- if (edid_ext[j+1] & 7)
- max_vfreq = edid_ext[j+10] + ((edid_ext[j+11] & 3) << 8);
- else
- max_vfreq = edid_ext[j+10];
-
- if (max_vfreq && min_vfreq) {
- connector->display_info.monitor_range.max_vfreq = max_vfreq;
- connector->display_info.monitor_range.min_vfreq = min_vfreq;
-
- return;
- }
- }
- j++;
- }
- }
-
- static int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
- struct amdgpu_hdmi_vsdb_info *vsdb_info)
- {
- struct drm_connector *connector = &aconnector->base;
-
- vsdb_info->replay_mode = connector->display_info.amd_vsdb.replay_mode;
- vsdb_info->amd_vsdb_version = connector->display_info.amd_vsdb.version;
-
- return connector->display_info.amd_vsdb.version != 0;
- }
-
- static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
- const struct edid *edid,
- struct amdgpu_hdmi_vsdb_info *vsdb_info)
- {
- u8 *edid_ext = NULL;
- int i;
- bool valid_vsdb_found = false;
-
- /*----- drm_find_cea_extension() -----*/
- /* No EDID or EDID extensions */
- if (edid == NULL || edid->extensions == 0)
- return -ENODEV;
-
- /* Find CEA extension */
- for (i = 0; i < edid->extensions; i++) {
- edid_ext = (uint8_t *)edid + EDID_LENGTH * (i + 1);
- if (edid_ext[0] == CEA_EXT)
- break;
- }
-
- if (i == edid->extensions)
- return -ENODEV;
-
- /*----- cea_db_offsets() -----*/
- if (edid_ext[0] != CEA_EXT)
- return -ENODEV;
-
- valid_vsdb_found = parse_edid_cea(aconnector, edid_ext, EDID_LENGTH, vsdb_info);
-
- return valid_vsdb_found ? i : -ENODEV;
- }
-
- /**
- * amdgpu_dm_update_freesync_caps - Update Freesync capabilities
- *
- * @connector: Connector to query.
- * @drm_edid: DRM EDID from monitor
- * @do_mccs: Controls whether MCCS (Monitor Control Command Set) over
- * DDC (Display Data Channel) transactions are performed. When true,
- * the driver queries the monitor to get or update additional FreeSync
- * capability information. When false, these transactions are skipped.
- *
- * Amdgpu supports Freesync in DP and HDMI displays, and it is required to keep
- * track of some of the display information in the internal data struct used by
- * amdgpu_dm. This function checks which type of connector we need to set the
- * FreeSync parameters.
- */
- void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
- const struct drm_edid *drm_edid, bool do_mccs)
- {
- int i = 0;
- struct amdgpu_dm_connector *amdgpu_dm_connector =
- to_amdgpu_dm_connector(connector);
- struct dm_connector_state *dm_con_state = NULL;
- struct dc_sink *sink;
- struct amdgpu_device *adev = drm_to_adev(connector->dev);
- struct amdgpu_hdmi_vsdb_info vsdb_info = {0};
- const struct edid *edid;
- bool freesync_capable = false;
- enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE;
-
- if (!connector->state) {
- drm_err(adev_to_drm(adev), "%s - Connector has no state", __func__);
- goto update;
- }
-
- sink = amdgpu_dm_connector->dc_sink ?
- amdgpu_dm_connector->dc_sink :
- amdgpu_dm_connector->dc_em_sink;
-
- drm_edid_connector_update(connector, drm_edid);
-
- if (!drm_edid || !sink) {
- dm_con_state = to_dm_connector_state(connector->state);
-
- amdgpu_dm_connector->min_vfreq = 0;
- amdgpu_dm_connector->max_vfreq = 0;
- freesync_capable = false;
-
- goto update;
- }
-
- dm_con_state = to_dm_connector_state(connector->state);
-
- if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version))
- goto update;
-
- edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw()
-
- /* Some eDP panels only have the refresh rate range info in DisplayID */
- if ((connector->display_info.monitor_range.min_vfreq == 0 ||
- connector->display_info.monitor_range.max_vfreq == 0))
- parse_edid_displayid_vrr(connector, edid);
-
- if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
- sink->sink_signal == SIGNAL_TYPE_EDP)) {
- if (amdgpu_dm_connector->dc_link &&
- amdgpu_dm_connector->dc_link->dpcd_caps.allow_invalid_MSA_timing_param) {
- amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq;
- amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq;
- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
- freesync_capable = true;
- }
-
- get_amd_vsdb(amdgpu_dm_connector, &vsdb_info);
-
- if (vsdb_info.replay_mode) {
- amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_info.replay_mode;
- amdgpu_dm_connector->vsdb_info.amd_vsdb_version = vsdb_info.amd_vsdb_version;
- amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP;
- }
-
- } else if (drm_edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) {
- i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
- if (i >= 0) {
- amdgpu_dm_connector->vsdb_info = vsdb_info;
- sink->edid_caps.freesync_vcp_code = vsdb_info.freesync_mccs_vcp_code;
-
- if (vsdb_info.freesync_supported) {
- amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz;
- amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz;
- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
- freesync_capable = true;
-
- connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz;
- connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
- }
- }
- }
-
- if (amdgpu_dm_connector->dc_link)
- as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link);
-
- if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) {
- i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
- if (i >= 0) {
- amdgpu_dm_connector->vsdb_info = vsdb_info;
- sink->edid_caps.freesync_vcp_code = vsdb_info.freesync_mccs_vcp_code;
-
- if (vsdb_info.freesync_supported && vsdb_info.amd_vsdb_version > 0) {
- amdgpu_dm_connector->pack_sdp_v1_3 = true;
- amdgpu_dm_connector->as_type = as_type;
-
- amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz;
- amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz;
- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
- freesync_capable = true;
-
- connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz;
- connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
- }
- }
- }
-
- /* Handle MCCS */
- if (do_mccs) {
- dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
-
- if (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)
- freesync_capable = false;
-
- if (sink->mccs_caps.freesync_supported && freesync_capable)
- dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
- }
-
- update:
- if (dm_con_state)
- dm_con_state->freesync_capable = freesync_capable;
-
- if (connector->state && amdgpu_dm_connector->dc_link && !freesync_capable &&
- amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported) {
- amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported = false;
- amdgpu_dm_connector->dc_link->replay_settings.replay_feature_enabled = false;
- }
-
- if (connector->vrr_capable_property)
- drm_connector_set_vrr_capable_property(connector,
- freesync_capable);
- }
-
void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
{
struct amdgpu_device *adev = drm_to_adev(dev);
@@@ -14018,12 -7495,6 +7495,6 @@@
mutex_unlock(&adev->dm.dc_lock);
}
- static inline void amdgpu_dm_exit_ips_for_hw_access(struct dc *dc)
- {
- if (dc->ctx->dmub_srv && !dc->ctx->dmub_srv->idle_exit_counter)
- dc_exit_ips_for_hw_access(dc);
- }
-
void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
u32 value, const char *func_name)
{
@@@ -14052,13 -7523,6 +7523,6 @@@ uint32_t dm_read_reg_func(const struct
}
#endif
- if (ctx->dmub_srv &&
- ctx->dmub_srv->reg_helper_offload.gather_in_progress &&
- !ctx->dmub_srv->reg_helper_offload.should_burst_write) {
- ASSERT(false);
- return 0;
- }
-
amdgpu_dm_exit_ips_for_hw_access(ctx->dc);
value = cgs_read_register(ctx->cgs_device, address);
@@@ -14068,179 -7532,6 +7532,6 @@@
return value;
}
- int amdgpu_dm_process_dmub_aux_transfer_sync(
- struct dc_context *ctx,
- unsigned int link_index,
- struct aux_payload *payload,
- enum aux_return_code_type *operation_result)
- {
- struct amdgpu_device *adev = ctx->driver_context;
- struct dmub_notification *p_notify = adev->dm.dmub_notify;
- int ret = -1;
-
- mutex_lock(&adev->dm.dpia_aux_lock);
- if (!dc_process_dmub_aux_transfer_async(ctx->dc, link_index, payload)) {
- *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
- goto out;
- }
-
- if (!wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) {
- drm_err(adev_to_drm(adev), "wait_for_completion_timeout timeout!");
- *operation_result = AUX_RET_ERROR_TIMEOUT;
- goto out;
- }
-
- if (p_notify->result != AUX_RET_SUCCESS) {
- /*
- * Transient states before tunneling is enabled could
- * lead to this error. We can ignore this for now.
- */
- if (p_notify->result == AUX_RET_ERROR_PROTOCOL_ERROR) {
- drm_warn(adev_to_drm(adev), "DPIA AUX failed on 0x%x(%d), error %d\n",
- payload->address, payload->length,
- p_notify->result);
- }
- *operation_result = p_notify->result;
- goto out;
- }
-
- payload->reply[0] = adev->dm.dmub_notify->aux_reply.command & 0xF;
- if (adev->dm.dmub_notify->aux_reply.command & 0xF0)
- /* The reply is stored in the top nibble of the command. */
- payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF;
-
- /*write req may receive a byte indicating partially written number as well*/
- if (p_notify->aux_reply.length)
- memcpy(payload->data, p_notify->aux_reply.data,
- p_notify->aux_reply.length);
-
- /* success */
- ret = p_notify->aux_reply.length;
- *operation_result = p_notify->result;
- out:
- reinit_completion(&adev->dm.dmub_aux_transfer_done);
- mutex_unlock(&adev->dm.dpia_aux_lock);
- return ret;
- }
-
- static void abort_fused_io(
- struct dc_context *ctx,
- const struct dmub_cmd_fused_request *request
- )
- {
- union dmub_rb_cmd command = { 0 };
- struct dmub_rb_cmd_fused_io *io = &command.fused_io;
-
- io->header.type = DMUB_CMD__FUSED_IO;
- io->header.sub_type = DMUB_CMD__FUSED_IO_ABORT;
- io->header.payload_bytes = sizeof(*io) - sizeof(io->header);
- io->request = *request;
- dm_execute_dmub_cmd(ctx, &command, DM_DMUB_WAIT_TYPE_NO_WAIT);
- }
-
- static bool execute_fused_io(
- struct amdgpu_device *dev,
- struct dc_context *ctx,
- union dmub_rb_cmd *commands,
- uint8_t count,
- uint32_t timeout_us
- )
- {
- const uint8_t ddc_line = commands[0].fused_io.request.u.aux.ddc_line;
-
- if (ddc_line >= ARRAY_SIZE(dev->dm.fused_io))
- return false;
-
- struct fused_io_sync *sync = &dev->dm.fused_io[ddc_line];
- struct dmub_rb_cmd_fused_io *first = &commands[0].fused_io;
- const bool result = dm_execute_dmub_cmd_list(ctx, count, commands, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)
- && first->header.ret_status
- && first->request.status == FUSED_REQUEST_STATUS_SUCCESS;
-
- if (!result)
- return false;
-
- while (wait_for_completion_timeout(&sync->replied, usecs_to_jiffies(timeout_us))) {
- reinit_completion(&sync->replied);
-
- struct dmub_cmd_fused_request *reply = (struct dmub_cmd_fused_request *) sync->reply_data;
-
- static_assert(sizeof(*reply) <= sizeof(sync->reply_data), "Size mismatch");
-
- if (reply->identifier == first->request.identifier) {
- first->request = *reply;
- return true;
- }
- }
-
- reinit_completion(&sync->replied);
- first->request.status = FUSED_REQUEST_STATUS_TIMEOUT;
- abort_fused_io(ctx, &first->request);
- return false;
- }
-
- bool amdgpu_dm_execute_fused_io(
- struct amdgpu_device *dev,
- struct dc_link *link,
- union dmub_rb_cmd *commands,
- uint8_t count,
- uint32_t timeout_us)
- {
- struct amdgpu_display_manager *dm = &dev->dm;
-
- mutex_lock(&dm->dpia_aux_lock);
-
- const bool result = execute_fused_io(dev, link->ctx, commands, count, timeout_us);
-
- mutex_unlock(&dm->dpia_aux_lock);
- return result;
- }
-
- int amdgpu_dm_process_dmub_set_config_sync(
- struct dc_context *ctx,
- unsigned int link_index,
- struct set_config_cmd_payload *payload,
- enum set_config_status *operation_result)
- {
- struct amdgpu_device *adev = ctx->driver_context;
- bool is_cmd_complete;
- int ret;
-
- mutex_lock(&adev->dm.dpia_aux_lock);
- is_cmd_complete = dc_process_dmub_set_config_async(ctx->dc,
- link_index, payload, adev->dm.dmub_notify);
-
- if (is_cmd_complete || wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) {
- ret = 0;
- *operation_result = adev->dm.dmub_notify->sc_status;
- } else {
- drm_err(adev_to_drm(adev), "wait_for_completion_timeout timeout!");
- ret = -1;
- *operation_result = SET_CONFIG_UNKNOWN_ERROR;
- }
-
- if (!is_cmd_complete)
- reinit_completion(&adev->dm.dmub_aux_transfer_done);
- mutex_unlock(&adev->dm.dpia_aux_lock);
- return ret;
- }
-
- bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
- {
- struct amdgpu_device *adev = ctx->driver_context;
-
- guard(spinlock_irqsave)(&adev->dm.dmub_lock);
- return dc_dmub_srv_cmd_run(ctx->dmub_srv, cmd, wait_type);
- }
-
- bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
- {
- struct amdgpu_device *adev = ctx->driver_context;
-
- guard(spinlock_irqsave)(&adev->dm.dmub_lock);
- return dc_dmub_srv_cmd_run_list(ctx->dmub_srv, count, cmd, wait_type);
- }
-
void dm_acpi_process_phy_transition_interlock(
const struct dc_context *ctx,
struct dm_process_phy_transition_init_params process_phy_transition_init_params)
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-07-17 14:40 Mark Brown
2026-07-17 15:12 ` Mark Brown
0 siblings, 1 reply; 41+ messages in thread
From: Mark Brown @ 2026-07-17 14:40 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Chenyu Chen, Dmytro Laktyushkin, Gabe Teeger,
George Zhang, Linux Kernel Mailing List, Linux Next Mailing List,
Matthew Stewart, Peichen Huang, Pengpeng Hou
[-- Attachment #1: Type: text/plain, Size: 6755 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
between commits:
6351003b1f4ec ("drm/amd/display: wire DCN42B mcache programming callback")
57cf172be2827 ("drm/amd/display: fix dcn42b det allocation order")
c4bc7ffb91586 ("drm/amd/display: Fix DCN42B null registers & register masks")
from the drm-fixes tree and commits:
85453fb4ff726 ("drm/amd/display: wire DCN42B mcache programming callback")
183bbded999a7 ("drm/amd/display: fix dcn42b det allocation order")
fd651b9a3be9e ("drm/amd/display: Add DCN42B VID_CRC_CONTROL and HBLANK_CONTROL registers")
219fb1f4c5b91 ("drm/amd/display: Enable zstate support and fix seamless boot")
b7d69145907cd ("drm/amd/display: Fix DCN42B null registers & register masks")
6cefc59d36667 ("drm/amd/display: Enable IPS support for DCN4 Variant")
329baa1c5f62b ("drm/amd/display: Enable PSR and Replay on DCN4 variant [Part 2]")
e14fcf9e5d2b5 ("drm/amd/display: correct encoder minimal creation")
d2184b1ba1be2 ("drm/amd/display: Enable pstate for DCN4 non-emulation builds")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
index 94e166c0a9b0b,2334bc5b75b8f..0000000000000
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
@@@ -134,6 -134,19 +134,6 @@@
#define regHUBP3_HUBPREQ_DEBUG 0x088d
#define regHUBP3_HUBPREQ_DEBUG_BASE_IDX 2
-#define regDP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL 0x3687
-#define regDP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL_BASE_IDX 2
-#define regDP_SYM32_ENC1_DP_SYM32_ENC_VID_CRC_CONTROL 0x375b
-#define regDP_SYM32_ENC1_DP_SYM32_ENC_VID_CRC_CONTROL_BASE_IDX 2
-#define regDP_SYM32_ENC2_DP_SYM32_ENC_VID_CRC_CONTROL 0x382f
-#define regDP_SYM32_ENC2_DP_SYM32_ENC_VID_CRC_CONTROL_BASE_IDX 2
-#define regDP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL 0x366b
-#define regDP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL_BASE_IDX 2
-#define regDP_SYM32_ENC1_DP_SYM32_ENC_HBLANK_CONTROL 0x373f
-#define regDP_SYM32_ENC1_DP_SYM32_ENC_HBLANK_CONTROL_BASE_IDX 2
-#define regDP_SYM32_ENC2_DP_SYM32_ENC_HBLANK_CONTROL 0x3813
-#define regDP_SYM32_ENC2_DP_SYM32_ENC_HBLANK_CONTROL_BASE_IDX 2
-
enum dcn401_clk_src_array_id {
DCN401_CLK_SRC_PLL0,
DCN401_CLK_SRC_PLL1,
@@@ -253,10 -266,10 +253,10 @@@ static struct bios_registers bios_regs
static struct dce110_clk_src_regs clk_src_regs[5];
static const struct dce110_clk_src_shift cs_shift = {
- CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT)
+ CS_COMMON_MASK_SH_LIST_DCN4_0_1(__SHIFT)
};
static const struct dce110_clk_src_mask cs_mask = {
- CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK)
+ CS_COMMON_MASK_SH_LIST_DCN4_0_1(_MASK)
};
#define abm_regs_init(id) \
ABM_DCN42B_REG_LIST_RI(id)
@@@ -351,7 -364,7 +351,7 @@@ static const struct dcn10_link_enc_mas
LINK_ENCODER_MASK_SH_LIST_DCN42B(_MASK)};
#define hpo_dp_stream_encoder_reg_init(id) \
- DCN42B_HPO_DP_STREAM_ENC_REG_LIST_RI(id)
+ DCN42_HPO_DP_STREAM_ENC_REG_LIST_RI(id)
static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4];
@@@ -775,7 -788,7 +775,7 @@@ static const struct dc_debug_options de
.underflow_assert_delay_us = 0xFFFFFFFF,
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
- .pstate_enabled = false,
+ .pstate_enabled = true,
.enable_mem_low_power = {
.bits = {
.vga = false,
@@@ -801,7 -814,7 +801,7 @@@
}
},
.seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT,
- .enable_z9_disable_interface = false, /* Allow support for the PMFW interface for disable Z9*/
+ .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/
.minimum_z8_residency_time = 1, /* Always allow when other conditions are met */
.support_eDP1_5 = true,
.use_max_lb = true,
@@@ -823,7 -836,7 +823,7 @@@
.disable_timeout = true,
.min_disp_clk_khz = 50000,
.static_screen_wait_frames = 2,
- .disable_z10 = true,
+ .disable_z10 = false,
.ignore_pg = true,
.disable_stutter_for_wm_program = true,
.min_deep_sleep_dcfclk_khz = 8000,
@@@ -1034,9 -1047,9 +1034,9 @@@ static struct hubp *dcn42b_hubp_create
}
static const struct dc_panel_config dcn42b_panel_config_defaults = {
.psr = {
- .disable_psr = true,
+ .disable_psr = false,
.disallow_psrsu = true,
- .disallow_replay = true,
+ .disallow_replay = false,
},
.ilr = {
.optimize_edp_link_rate = true,
@@@ -1842,7 -1855,7 +1842,7 @@@ static struct link_encoder *dcn42b_link
{
struct dcn20_link_encoder *enc20;
- if ((unsigned int)(eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc)
+ if ((unsigned int)(eng_id - ENGINE_ID_DIGA) >= ctx->dc->res_pool->res_cap->num_dig_link_enc)
return NULL;
enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
@@@ -1854,6 -1867,8 +1854,8 @@@
ctx,
&link_enc_feature,
&link_enc_regs[eng_id - ENGINE_ID_DIGA],
+ &le_shift,
+ &le_mask,
eng_id);
return &enc20->enc10.base;
@@@ -2002,11 -2017,10 +2004,10 @@@ static bool dcn42b_resource_construct
dc->caps.dmcub_support = true;
dc->caps.is_apu = true;
dc->caps.seamless_odm = true;
- dc->caps.zstate_support = false;
- dc->caps.ips_support = false;
+ dc->caps.zstate_support = true;
+ dc->caps.ips_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
dc->caps.vtotal_limited_by_fp2 = true;
- dc->config.disable_ips = DMUB_IPS_DISABLE_ALL;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* Re: linux-next: manual merge of the drm tree with the drm-fixes tree
2026-07-17 14:40 Mark Brown
@ 2026-07-17 15:12 ` Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-07-17 15:12 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Chenyu Chen, Dmytro Laktyushkin, Gabe Teeger,
George Zhang, Linux Kernel Mailing List, Linux Next Mailing List,
Matthew Stewart, Peichen Huang, Pengpeng Hou
[-- Attachment #1: Type: text/plain, Size: 859 bytes --]
On Fri, Jul 17, 2026 at 03:40:07PM +0100, Mark Brown wrote:
> Today's linux-next merge of the drm tree got a conflict in:
>
> drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
>
> between commits:
>
> 6351003b1f4ec ("drm/amd/display: wire DCN42B mcache programming callback")
> 57cf172be2827 ("drm/amd/display: fix dcn42b det allocation order")
> c4bc7ffb91586 ("drm/amd/display: Fix DCN42B null registers & register masks")
>
> from the drm-fixes tree and commits:
>
> 85453fb4ff726 ("drm/amd/display: wire DCN42B mcache programming callback")
Actually the merge here doesn't build. I'll try to fix it up but
*please* try not to do this constant, routine cherry picking. Sometimes
it's the sensible thing to do but most of the time I'd expect to see the
fixes go up onto the -next branch with a merge.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread
* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-07-10 12:11 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-07-10 12:11 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, David Francis, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 2289 bytes --]
Hi all,
Today's linux-next merge of the drm tree got conflicts in:
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
between commits:
8a93f77aec655 ("drm/amdkfd: Don't acquire buffers during CRIU queue restore.")
47ea05f246beb ("drm/amdkfd: Check bounds on CRIU restore queue type and mqd size")
from the drm-fixes tree and commits:
f19d8086f6644 ("drm/amdkfd: Check bounds on CRIU restore queue type and mqd size")
1cafa8b29e029 ("drm/amdkfd: Don't acquire buffers during CRIU queue restore.")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
index 641b8ada82a03,c9f9f7a871117..0000000000000
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
@@@ -333,6 -333,8 +333,8 @@@ int debug_refresh_runlist(struct device
bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm,
struct qcm_process_device *qpd,
int doorbell_off, u32 *queue_format);
+ int kfd_reset_queue_mes(struct device_queue_manager *dqm, int queue_type,
+ int pipe, int queue, unsigned int db);
size_t mqd_size_from_queue_type(struct device_queue_manager *dqm,
enum kfd_queue_type type);
diff --combined drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index 9ccbc6e5b27b3,97e77a5a35e51..0000000000000
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@@ -1055,7 -1055,7 +1055,7 @@@ int kfd_criu_restore_queue(struct kfd_p
ctl_stack = mqd + q_data->mqd_size;
memset(&qp, 0, sizeof(qp));
- set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->adev->gfx.xcc_mask));
+ set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->xcc_mask));
print_queue_properties(&qp);
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-05-29 22:00 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-05-29 22:00 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Christian König, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 2218 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
between commit:
1c824497d8acd ("drm/amdgpu: fix calling VM invalidation in amdgpu_hmm_invalidate_gfx")
from the drm-fixes tree and commit:
4cdbba5a16aaf ("drm/amdgpu: restructure VM state machine v4")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index c9f88ecce1a75,a99d01f9dc750..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@@ -1629,9 -1598,8 +1598,9 @@@ int amdgpu_vm_handle_moved(struct amdgp
struct amdgpu_vm *vm,
struct ww_acquire_ctx *ticket)
{
- struct amdgpu_bo_va *bo_va;
+ struct amdgpu_bo_va *bo_va, *tmp;
struct dma_resv *resv;
+ struct amdgpu_bo *bo;
bool clear, unlock;
int r;
@@@ -1645,19 -1609,17 +1610,18 @@@
r = amdgpu_vm_bo_update(adev, bo_va, false);
if (r)
return r;
- spin_lock(&vm->status_lock);
}
- while (!list_empty(&vm->invalidated)) {
- bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
- base.vm_status);
- bo = bo_va->base.bo;
- resv = bo->tbo.base.resv;
- spin_unlock(&vm->status_lock);
+ spin_lock(&vm->individual_lock);
+ while (!list_empty(&vm->individual.moved)) {
+ bo_va = list_first_entry(&vm->individual.moved,
+ typeof(*bo_va), base.vm_status);
+ resv = bo_va->base.bo->tbo.base.resv;
+ spin_unlock(&vm->individual_lock);
/* Try to reserve the BO to avoid clearing its ptes */
- if (!adev->debug_vm && dma_resv_trylock(resv)) {
+ if (!adev->debug_vm && !amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) &&
+ dma_resv_trylock(resv)) {
clear = false;
unlock = true;
/* The caller is already holding the reservation lock */
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-04-03 13:33 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-04-03 13:33 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Lijo Lazar, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 8371 bytes --]
Hi all,
Today's linux-next merge of the drm tree got conflicts in:
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
between commit:
a3ffaa5b397f4 ("drm/amdgpu/pm: drop SMU driver if version not matched messages")
from the drm-fixes tree and commits:
6b0a6116286ef ("drm/amd/pm: Unify version check in SMUv11")
353f200825051 ("drm/amd/pm: Unify version check in SMUv12")
964e532d58378 ("drm/amd/pm: Unify version check in SMUv14")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index 7ca8fdd23206e,d68ceee16d8f1..0000000000000
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@@ -192,81 -192,6 +192,6 @@@ int smu_v11_0_check_fw_status(struct sm
return -EIO;
}
- int smu_v11_0_check_fw_version(struct smu_context *smu)
- {
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
- switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
- case IP_VERSION(11, 0, 0):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV10;
- break;
- case IP_VERSION(11, 0, 9):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV12;
- break;
- case IP_VERSION(11, 0, 5):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV14;
- break;
- case IP_VERSION(11, 0, 7):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Sienna_Cichlid;
- break;
- case IP_VERSION(11, 0, 11):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder;
- break;
- case IP_VERSION(11, 5, 0):
- case IP_VERSION(11, 5, 2):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_VANGOGH;
- break;
- case IP_VERSION(11, 0, 12):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish;
- break;
- case IP_VERSION(11, 0, 13):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Beige_Goby;
- break;
- case IP_VERSION(11, 0, 8):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Cyan_Skillfish;
- break;
- case IP_VERSION(11, 0, 2):
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_ARCT;
- break;
- default:
- dev_err(smu->adev->dev, "smu unsupported IP version: 0x%x.\n",
- amdgpu_ip_version(adev, MP1_HWIP, 0));
- smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV;
- break;
- }
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- if (if_version != smu->smc_driver_if_version) {
- dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
- }
-
- return ret;
- }
-
static int smu_v11_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
diff --combined drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
index ac5e44dff6c97,f09da4d14510b..0000000000000
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
@@@ -70,42 -70,6 +70,6 @@@ int smu_v12_0_check_fw_status(struct sm
return -EIO;
}
- int smu_v12_0_check_fw_version(struct smu_context *smu)
- {
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- if (if_version != smu->smc_driver_if_version) {
- dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
- }
-
- return ret;
- }
-
int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate)
{
if (!smu->is_apu)
diff --combined drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
index e38354c694c95,d0a8df1aa6b64..0000000000000
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
@@@ -229,66 -229,6 +229,6 @@@ int smu_v14_0_check_fw_status(struct sm
return -EIO;
}
- int smu_v14_0_check_fw_version(struct smu_context *smu)
- {
- struct amdgpu_device *adev = smu->adev;
- uint32_t if_version = 0xff, smu_version = 0xff;
- uint8_t smu_program, smu_major, smu_minor, smu_debug;
- int ret = 0;
-
- ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
- if (ret)
- return ret;
-
- smu_program = (smu_version >> 24) & 0xff;
- smu_major = (smu_version >> 16) & 0xff;
- smu_minor = (smu_version >> 8) & 0xff;
- smu_debug = (smu_version >> 0) & 0xff;
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
- switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
- case IP_VERSION(14, 0, 0):
- case IP_VERSION(14, 0, 4):
- case IP_VERSION(14, 0, 5):
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0;
- break;
- case IP_VERSION(14, 0, 1):
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_1;
- break;
- case IP_VERSION(14, 0, 2):
- case IP_VERSION(14, 0, 3):
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_2;
- break;
- default:
- dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n",
- amdgpu_ip_version(adev, MP1_HWIP, 0));
- smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_INV;
- break;
- }
-
- if (adev->pm.fw)
- dev_dbg(smu->adev->dev, "smu fw reported program %d, version = 0x%08x (%d.%d.%d)\n",
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
-
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
- * 2. New fw usually brings some optimizations. But that's visible
- * only on the paired driver.
- * Considering above, we just leave user a verbal message instead
- * of halt driver loading.
- */
- if (if_version != smu->smc_driver_if_version) {
- dev_info(adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
- "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
- smu->smc_driver_if_version, if_version,
- smu_program, smu_version, smu_major, smu_minor, smu_debug);
- }
-
- return ret;
- }
-
static int smu_v14_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
{
struct amdgpu_device *adev = smu->adev;
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-03-27 20:52 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-03-27 20:52 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Kernel Mailing List, Linux Next Mailing List, Matt Roper,
Rodrigo Vivi
[-- Attachment #1: Type: text/plain, Size: 24734 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/xe/xe_wa.c
between commit:
56781a4597706c ("drm/xe: Implement recent spec updates to Wa_16025250150")
from the drm-fixes tree and commits:
a31566762d4075 ("drm/xe: Implement recent spec updates to Wa_16025250150")
9f49e185ee31d5 ("drm/xe/wa: Drop redundant entries for Wa_16021867713 & Wa_14019449301")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/xe/xe_wa.c
index d7e309ad9abaf5,546296f0220b5f..00000000000000
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@@ -111,6 -111,17 +111,17 @@@
* difference of how they are maintained in the code. In xe it uses the
* xe_rtp infrastructure so the workarounds can be kept in tables, following
* a more declarative approach rather than procedural.
+ *
+ * .. note::
+ * When a workaround applies to every single known IP version in a range,
+ * the preferred handling is to use a single range-based RTP entry rather
+ * than individual entries for each version, even if some of the intermediate
+ * version numbers are currently unused. If a new intermediate IP version
+ * appears in the future and is enabled in the driver, any existing
+ * range-based entries that contain the new version number will need to be
+ * analyzed to determine whether their workarounds should apply to the new
+ * version, or whether any existing range based entries needs to be split
+ * into two entries that do not include the new intermediate version.
*/
#undef XE_REG_MCR
@@@ -120,6 -131,8 +131,8 @@@ __diag_push()
__diag_ignore_all("-Woverride-init", "Allow field overrides in table");
static const struct xe_rtp_entry_sr gt_was[] = {
+ /* Workarounds applying over a range of IPs */
+
{ XE_RTP_NAME("14011060649"),
XE_RTP_RULES(MEDIA_VERSION_RANGE(1200, 1255),
ENGINE_CLASS(VIDEO_DECODE),
@@@ -135,6 -148,27 +148,27 @@@
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1260)),
XE_RTP_ACTIONS(CLR(MISCCPCTL, DOP_CLOCK_GATE_RENDER_ENABLE))
},
+ { XE_RTP_NAME("16021867713"),
+ XE_RTP_RULES(MEDIA_VERSION_RANGE(1300, 3002),
+ ENGINE_CLASS(VIDEO_DECODE)),
+ XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F1C(0), MFXPIPE_CLKGATE_DIS)),
+ XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
+ },
+ { XE_RTP_NAME("14019449301"),
+ XE_RTP_RULES(MEDIA_VERSION_RANGE(1301, 2000), ENGINE_CLASS(VIDEO_DECODE)),
+ XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F08(0), CG3DDISHRS_CLKGATE_DIS)),
+ XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
+ },
+ { XE_RTP_NAME("16028005424"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), OR,
+ MEDIA_VERSION_RANGE(1301, 3500)),
+ XE_RTP_ACTIONS(SET(GUC_INTR_CHICKEN, DISABLE_SIGNALING_ENGINES))
+ },
+ { XE_RTP_NAME("14026578760"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3510, 3511), OR,
+ MEDIA_VERSION(3503)),
+ XE_RTP_ACTIONS(SET(GAMSTLB_CTRL, DIS_PEND_GPA_LINK))
+ },
/* DG1 */
@@@ -191,10 -225,6 +225,6 @@@
/* Xe_LPG */
- { XE_RTP_NAME("14015795083"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1270, 1271), GRAPHICS_STEP(A0, B0)),
- XE_RTP_ACTIONS(CLR(MISCCPCTL, DOP_CLOCK_GATE_RENDER_ENABLE))
- },
{ XE_RTP_NAME("14018575942"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1270, 1274)),
XE_RTP_ACTIONS(SET(COMP_MOD_CTRL, FORCE_MISS_FTLB))
@@@ -206,12 -236,6 +236,6 @@@
/* Xe_LPM+ */
- { XE_RTP_NAME("16021867713"),
- XE_RTP_RULES(MEDIA_VERSION(1300),
- ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F1C(0), MFXPIPE_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
{ XE_RTP_NAME("22016670082"),
XE_RTP_RULES(MEDIA_VERSION(1300)),
XE_RTP_ACTIONS(SET(XELPMP_SQCNT1, ENFORCE_RAR))
@@@ -225,17 -249,6 +249,6 @@@
XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), IECPUNIT_CLKGATE_DIS)),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
},
- { XE_RTP_NAME("16021867713"),
- XE_RTP_RULES(MEDIA_VERSION(2000),
- ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F1C(0), MFXPIPE_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
- { XE_RTP_NAME("14019449301"),
- XE_RTP_RULES(MEDIA_VERSION(2000), ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F08(0), CG3DDISHRS_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
/* Xe2_HPG */
@@@ -251,20 -264,6 +264,6 @@@
SET(LSC_CHICKEN_BIT_0_UDW, L3_128B_256B_WRT_DIS))
},
- /* Xe2_HPM */
-
- { XE_RTP_NAME("16021867713"),
- XE_RTP_RULES(MEDIA_VERSION(1301),
- ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F1C(0), MFXPIPE_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
- { XE_RTP_NAME("14019449301"),
- XE_RTP_RULES(MEDIA_VERSION(1301), ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F08(0), CG3DDISHRS_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
-
/* Xe3_LPG */
{ XE_RTP_NAME("14021871409"),
@@@ -274,43 -273,44 +273,44 @@@
/* Xe3_LPM */
- { XE_RTP_NAME("16021867713"),
- XE_RTP_RULES(MEDIA_VERSION(3000),
- ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F1C(0), MFXPIPE_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
{ XE_RTP_NAME("16021865536"),
- XE_RTP_RULES(MEDIA_VERSION(3000),
+ XE_RTP_RULES(MEDIA_VERSION_RANGE(3000, 3002),
ENGINE_CLASS(VIDEO_DECODE)),
XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), IECPUNIT_CLKGATE_DIS)),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
},
- { XE_RTP_NAME("16021865536"),
- XE_RTP_RULES(MEDIA_VERSION(3002),
- ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), IECPUNIT_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
- { XE_RTP_NAME("16021867713"),
- XE_RTP_RULES(MEDIA_VERSION(3002),
- ENGINE_CLASS(VIDEO_DECODE)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F1C(0), MFXPIPE_CLKGATE_DIS)),
- XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
- },
{ XE_RTP_NAME("14021486841"),
XE_RTP_RULES(MEDIA_VERSION(3000), MEDIA_STEP(A0, B0),
ENGINE_CLASS(VIDEO_DECODE)),
XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), RAMDFTUNIT_CLKGATE_DIS)),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
},
+
+ /* Xe3P_LPG */
+
+ { XE_RTP_NAME("14025160223"),
+ XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0)),
+ XE_RTP_ACTIONS(SET(MMIOATSREQLIMIT_GAM_WALK_3D,
+ DIS_ATS_WRONLY_PG))
+ },
+ { XE_RTP_NAME("14026144927, 16029437861"),
+ XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0)),
+ XE_RTP_ACTIONS(SET(L3SQCREG2, L3_SQ_DISABLE_COAMA_2WAY_COH |
+ L3_SQ_DISABLE_COAMA))
+ },
+ { XE_RTP_NAME("14025635424"),
+ XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0)),
+ XE_RTP_ACTIONS(SET(GAMSTLB_CTRL2, STLB_SINGLE_BANK_MODE))
+ },
{ XE_RTP_NAME("16028005424"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005)),
+ XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0)),
XE_RTP_ACTIONS(SET(GUC_INTR_CHICKEN, DISABLE_SIGNALING_ENGINES))
},
};
static const struct xe_rtp_entry_sr engine_was[] = {
+ /* Workarounds applying over a range of IPs */
+
{ XE_RTP_NAME("22010931296, 18011464164, 14010919138"),
XE_RTP_RULES(GRAPHICS_VERSION(1200), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(FF_THREAD_MODE(RENDER_RING_BASE),
@@@ -346,6 -346,54 +346,54 @@@
XE_RTP_ACTIONS(SET(FF_SLICE_CS_CHICKEN1(RENDER_RING_BASE),
FFSC_PERCTX_PREEMPT_CTRL))
},
+ { XE_RTP_NAME("18032247524"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0, SEQUENTIAL_ACCESS_UPGRADE_DISABLE))
+ },
+ { XE_RTP_NAME("16018712365"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, XE2_ALLOC_DPA_STARVE_FIX_DIS))
+ },
+ { XE_RTP_NAME("14020338487"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(ROW_CHICKEN3, XE2_EUPEND_CHK_FLUSH_DIS))
+ },
+ { XE_RTP_NAME("14018471104"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, ENABLE_SMP_LD_RENDER_SURFACE_CONTROL))
+ },
+ /*
+ * Although this workaround isn't required for the RCS, disabling these
+ * reports has no impact for our driver or the GuC, so we go ahead and
+ * apply this to all engines for simplicity.
+ */
+ { XE_RTP_NAME("16021639441"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), OR,
+ MEDIA_VERSION_RANGE(1301, 2000)),
+ XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0),
+ GHWSP_CSB_REPORT_DIS |
+ PPHWSP_CSB_AND_TIMESTAMP_REPORT_DIS,
+ XE_RTP_ACTION_FLAG(ENGINE_BASE)))
+ },
+ { XE_RTP_NAME("14021402888"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 3005), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE))
+ },
+ { XE_RTP_NAME("13012615864"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 3005),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS))
+ },
+ { XE_RTP_NAME("18041344222"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 3000),
+ FUNC(xe_rtp_match_first_render_or_compute),
+ FUNC(xe_rtp_match_gt_has_discontiguous_dss_groups)),
+ XE_RTP_ACTIONS(SET(TDL_CHICKEN, EUSTALL_PERF_SAMPLING_DISABLE))
+ },
/* TGL */
@@@ -461,11 -509,6 +509,6 @@@
ENGINE_CLASS(COMPUTE)),
XE_RTP_ACTIONS(SET(RING_HWSTAM(RENDER_RING_BASE), ~0))
},
- { XE_RTP_NAME("14014999345"),
- XE_RTP_RULES(PLATFORM(PVC), ENGINE_CLASS(COMPUTE),
- GRAPHICS_STEP(B0, C0)),
- XE_RTP_ACTIONS(SET(CACHE_MODE_SS, DISABLE_ECC))
- },
/* Xe_LPG */
@@@ -488,149 -531,36 +531,36 @@@
/* Xe2_LPG */
- { XE_RTP_NAME("18032247524"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0, SEQUENTIAL_ACCESS_UPGRADE_DISABLE))
- },
- { XE_RTP_NAME("16018712365"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, XE2_ALLOC_DPA_STARVE_FIX_DIS))
- },
- { XE_RTP_NAME("14020338487"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(ROW_CHICKEN3, XE2_EUPEND_CHK_FLUSH_DIS))
- },
{ XE_RTP_NAME("18034896535, 16021540221"), /* 16021540221: GRAPHICS_STEP(A0, B0) */
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004),
FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(ROW_CHICKEN4, DISABLE_TDL_PUSH))
},
- { XE_RTP_NAME("14018471104"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, ENABLE_SMP_LD_RENDER_SURFACE_CONTROL))
- },
- /*
- * These two workarounds are the same, just applying to different
- * engines. Although Wa_18032095049 (for the RCS) isn't required on
- * all steppings, disabling these reports has no impact for our
- * driver or the GuC, so we go ahead and treat it the same as
- * Wa_16021639441 which does apply to all steppings.
- */
- { XE_RTP_NAME("18032095049, 16021639441"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004)),
- XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0),
- GHWSP_CSB_REPORT_DIS |
- PPHWSP_CSB_AND_TIMESTAMP_REPORT_DIS,
- XE_RTP_ACTION_FLAG(ENGINE_BASE)))
- },
{ XE_RTP_NAME("16018610683"),
XE_RTP_RULES(GRAPHICS_VERSION(2004), FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, SLM_WMTP_RESTORE))
},
- { XE_RTP_NAME("14021402888"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE))
- },
- { XE_RTP_NAME("13012615864"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS))
- },
/* Xe2_HPG */
- { XE_RTP_NAME("16018712365"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, XE2_ALLOC_DPA_STARVE_FIX_DIS))
- },
{ XE_RTP_NAME("16018737384"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2999),
FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(ROW_CHICKEN, EARLY_EOT_DIS))
},
- { XE_RTP_NAME("14020338487"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(ROW_CHICKEN3, XE2_EUPEND_CHK_FLUSH_DIS))
- },
- { XE_RTP_NAME("18032247524"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0, SEQUENTIAL_ACCESS_UPGRADE_DISABLE))
- },
- { XE_RTP_NAME("14018471104"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, ENABLE_SMP_LD_RENDER_SURFACE_CONTROL))
- },
- /*
- * Although this workaround isn't required for the RCS, disabling these
- * reports has no impact for our driver or the GuC, so we go ahead and
- * apply this to all engines for simplicity.
- */
- { XE_RTP_NAME("16021639441"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002)),
- XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0),
- GHWSP_CSB_REPORT_DIS |
- PPHWSP_CSB_AND_TIMESTAMP_REPORT_DIS,
- XE_RTP_ACTION_FLAG(ENGINE_BASE)))
- },
{ XE_RTP_NAME("14019811474"),
XE_RTP_RULES(GRAPHICS_VERSION(2001),
FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0, WR_REQ_CHAINING_DIS))
},
- { XE_RTP_NAME("14021402888"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE))
- },
{ XE_RTP_NAME("14021821874, 14022954250"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002),
FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, STK_ID_RESTRICT))
},
- { XE_RTP_NAME("13012615864"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS))
- },
- { XE_RTP_NAME("18041344222"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002),
- FUNC(xe_rtp_match_first_render_or_compute),
- FUNC(xe_rtp_match_not_sriov_vf),
- FUNC(xe_rtp_match_gt_has_discontiguous_dss_groups)),
- XE_RTP_ACTIONS(SET(TDL_CHICKEN, EUSTALL_PERF_SAMPLING_DISABLE))
- },
-
- /* Xe2_LPM */
-
- { XE_RTP_NAME("16021639441"),
- XE_RTP_RULES(MEDIA_VERSION(2000)),
- XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0),
- GHWSP_CSB_REPORT_DIS |
- PPHWSP_CSB_AND_TIMESTAMP_REPORT_DIS,
- XE_RTP_ACTION_FLAG(ENGINE_BASE)))
- },
-
- /* Xe2_HPM */
-
- { XE_RTP_NAME("16021639441"),
- XE_RTP_RULES(MEDIA_VERSION(1301)),
- XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0),
- GHWSP_CSB_REPORT_DIS |
- PPHWSP_CSB_AND_TIMESTAMP_REPORT_DIS,
- XE_RTP_ACTION_FLAG(ENGINE_BASE)))
- },
/* Xe3_LPG */
- { XE_RTP_NAME("14021402888"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE))
- },
{ XE_RTP_NAME("18034896535"),
XE_RTP_RULES(GRAPHICS_VERSION(3000), GRAPHICS_STEP(A0, B0),
FUNC(xe_rtp_match_first_render_or_compute)),
@@@ -643,34 -573,33 +573,33 @@@
SMP_FORCE_128B_OVERFETCH))
},
{ XE_RTP_NAME("14023061436"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001),
- FUNC(xe_rtp_match_first_render_or_compute), OR,
- GRAPHICS_VERSION_RANGE(3003, 3005),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005),
FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(TDL_CHICKEN, QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE))
},
- { XE_RTP_NAME("13012615864"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001), OR,
- GRAPHICS_VERSION_RANGE(3003, 3005),
- FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS))
- },
{ XE_RTP_NAME("16023105232"),
XE_RTP_RULES(MEDIA_VERSION_RANGE(1301, 3000), OR,
GRAPHICS_VERSION_RANGE(2001, 3001)),
XE_RTP_ACTIONS(SET(RING_PSMI_CTL(0), RC_SEMA_IDLE_MSG_DISABLE,
XE_RTP_ACTION_FLAG(ENGINE_BASE)))
},
- { XE_RTP_NAME("14021402888"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3003, 3005), FUNC(xe_rtp_match_first_render_or_compute)),
- XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE))
+
+ /* Xe3p_LPG*/
+
+ { XE_RTP_NAME("22021149932"),
+ XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, SAMPLER_LD_LSC_DISABLE))
},
- { XE_RTP_NAME("18041344222"),
- XE_RTP_RULES(GRAPHICS_VERSION(3000),
- FUNC(xe_rtp_match_first_render_or_compute),
- FUNC(xe_rtp_match_not_sriov_vf),
- FUNC(xe_rtp_match_gt_has_discontiguous_dss_groups)),
- XE_RTP_ACTIONS(SET(TDL_CHICKEN, EUSTALL_PERF_SAMPLING_DISABLE))
+ { XE_RTP_NAME("14025676848"),
+ XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(LSC_CHICKEN_BIT_0_UDW, LSCFE_SAME_ADDRESS_ATOMICS_COALESCING_DISABLE))
+ },
+ { XE_RTP_NAME("16028951944"),
+ XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0),
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(ROW_CHICKEN5, CPSS_AWARE_DIS))
},
};
@@@ -708,6 -637,30 +637,30 @@@ static const struct xe_rtp_entry_sr lrc
XE_RTP_RULES(GRAPHICS_VERSION(1200)),
XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, DISABLE_TDC_LOAD_BALANCING_CALC))
},
+ { XE_RTP_NAME("14019877138"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1255, 2004), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FD_END_COLLECT))
+ },
+ { XE_RTP_NAME("14019386621"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(VF_SCRATCHPAD, XE2_VFG_TED_CREDIT_INTERFACE_DISABLE))
+ },
+ { XE_RTP_NAME("14019988906"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FLSH_IGNORES_PSD))
+ },
+ { XE_RTP_NAME("18033852989"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST))
+ },
+ { XE_RTP_NAME("15016589081"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX))
+ },
+ { XE_RTP_NAME("14026781792"),
+ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3510), ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(FF_MODE, DIS_TE_PATCH_CTRL))
+ },
/* DG1 */
@@@ -744,10 -697,6 +697,6 @@@
XE_RTP_RULES(PLATFORM(DG2)),
XE_RTP_ACTIONS(SET(CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE))
},
- { XE_RTP_NAME("14019877138"),
- XE_RTP_RULES(PLATFORM(DG2)),
- XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FD_END_COLLECT))
- },
/* PVC */
@@@ -765,29 -714,9 +714,9 @@@
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1270, 1274)),
XE_RTP_ACTIONS(SET(CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE))
},
- { XE_RTP_NAME("14019877138"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1270, 1274), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FD_END_COLLECT))
- },
/* Xe2_LPG */
- { XE_RTP_NAME("14019386621"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(VF_SCRATCHPAD, XE2_VFG_TED_CREDIT_INTERFACE_DISABLE))
- },
- { XE_RTP_NAME("14019877138"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FD_END_COLLECT))
- },
- { XE_RTP_NAME("14019988906"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FLSH_IGNORES_PSD))
- },
- { XE_RTP_NAME("18033852989"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST))
- },
{ XE_RTP_NAME("14021567978"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED),
ENGINE_CLASS(RENDER)),
@@@ -807,20 -736,9 +736,9 @@@
DIS_PARTIAL_AUTOSTRIP |
DIS_AUTOSTRIP))
},
- { XE_RTP_NAME("15016589081"),
- XE_RTP_RULES(GRAPHICS_VERSION(2004), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX))
- },
/* Xe2_HPG */
- { XE_RTP_NAME("15010599737"),
- XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_SF_ROUND_NEAREST_EVEN))
- },
- { XE_RTP_NAME("14019386621"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(VF_SCRATCHPAD, XE2_VFG_TED_CREDIT_INTERFACE_DISABLE))
- },
+
{ XE_RTP_NAME("14020756599"),
XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(WM_CHICKEN3, HIZ_PLANE_COMPRESSION_DIS))
@@@ -842,18 -760,10 +760,10 @@@
DIS_PARTIAL_AUTOSTRIP |
DIS_AUTOSTRIP))
},
- { XE_RTP_NAME("15016589081"),
- XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX))
- },
{ XE_RTP_NAME("22021007897"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE))
},
- { XE_RTP_NAME("18033852989"),
- XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)),
- XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST))
- },
/* Xe3_LPG */
{ XE_RTP_NAME("14021490052"),
@@@ -945,7 -855,8 +855,8 @@@ void xe_wa_process_gt(struct xe_gt *gt
xe_rtp_process_ctx_enable_active_tracking(&ctx, gt->wa_active.gt,
ARRAY_SIZE(gt_was));
- xe_rtp_process_to_sr(&ctx, gt_was, ARRAY_SIZE(gt_was), >->reg_sr);
+ xe_rtp_process_to_sr(&ctx, gt_was, ARRAY_SIZE(gt_was),
+ >->reg_sr, false);
}
EXPORT_SYMBOL_IF_KUNIT(xe_wa_process_gt);
@@@ -963,7 -874,8 +874,8 @@@ void xe_wa_process_engine(struct xe_hw_
xe_rtp_process_ctx_enable_active_tracking(&ctx, hwe->gt->wa_active.engine,
ARRAY_SIZE(engine_was));
- xe_rtp_process_to_sr(&ctx, engine_was, ARRAY_SIZE(engine_was), &hwe->reg_sr);
+ xe_rtp_process_to_sr(&ctx, engine_was, ARRAY_SIZE(engine_was),
+ &hwe->reg_sr, false);
}
/**
@@@ -980,7 -892,8 +892,8 @@@ void xe_wa_process_lrc(struct xe_hw_eng
xe_rtp_process_ctx_enable_active_tracking(&ctx, hwe->gt->wa_active.lrc,
ARRAY_SIZE(lrc_was));
- xe_rtp_process_to_sr(&ctx, lrc_was, ARRAY_SIZE(lrc_was), &hwe->reg_lrc);
+ xe_rtp_process_to_sr(&ctx, lrc_was, ARRAY_SIZE(lrc_was),
+ &hwe->reg_lrc, true);
}
/**
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-03-27 20:46 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-03-27 20:46 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Asad Kamal, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 8039 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
between commit:
cdbc3b62cfc278 ("drm/amd/pm: Skip redundant UCLK restore in smu_v13_0_6")
from the drm-fixes tree and commits:
17f11bbbc76c8e ("drm/amd/pm: Skip redundant UCLK restore in smu_v13_0_6")
5da89a8afca14a ("drm/amd/pm: Add custom fclk setting support")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index 870bcc86fd7948,47554118978298..00000000000000
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@@ -373,6 -373,9 +373,9 @@@ static void smu_v13_0_12_init_caps(stru
} else {
smu_v13_0_12_tables_fini(smu);
}
+
+ if (fw_ver >= 0x04561000)
+ smu_v13_0_6_cap_set(smu, SMU_CAP(TEMP_AID_XCD_HBM));
}
static void smu_v13_0_6_init_caps(struct smu_context *smu)
@@@ -458,6 -461,7 +461,7 @@@
smu_v13_0_6_cap_set(smu, SMU_CAP(SDMA_RESET));
if ((pgm == 0 && fw_ver >= 0x00558200) ||
+ (pgm == 4 && fw_ver >= 0x04557100) ||
(pgm == 7 && fw_ver >= 0x07551400))
smu_v13_0_6_cap_set(smu, SMU_CAP(VCN_RESET));
}
@@@ -478,7 -482,7 +482,7 @@@ static int smu_v13_0_6_check_fw_version
{
int r;
- r = smu_v13_0_check_fw_version(smu);
+ r = smu_cmn_check_fw_version(smu);
/* Initialize caps flags once fw version is fetched */
if (!r)
smu_v13_0_x_init_caps(smu);
@@@ -1196,6 -1200,7 +1200,7 @@@ static int smu_v13_0_6_populate_umd_sta
struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table;
struct smu_dpm_table *soc_table = &dpm_context->dpm_tables.soc_table;
+ struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
pstate_table->gfxclk_pstate.min = SMU_DPM_TABLE_MIN(gfx_table);
@@@ -1213,6 -1218,12 +1218,12 @@@
pstate_table->socclk_pstate.curr.min = SMU_DPM_TABLE_MIN(soc_table);
pstate_table->socclk_pstate.curr.max = SMU_DPM_TABLE_MAX(soc_table);
+ pstate_table->fclk_pstate.min = SMU_DPM_TABLE_MIN(fclk_table);
+ pstate_table->fclk_pstate.peak = SMU_DPM_TABLE_MAX(fclk_table);
+ pstate_table->fclk_pstate.curr.min = SMU_DPM_TABLE_MIN(fclk_table);
+ pstate_table->fclk_pstate.curr.max = SMU_DPM_TABLE_MAX(fclk_table);
+ pstate_table->fclk_pstate.standard = SMU_DPM_TABLE_MIN(fclk_table);
+
if (gfx_table->count > SMU_13_0_6_UMD_PSTATE_GFXCLK_LEVEL &&
mem_table->count > SMU_13_0_6_UMD_PSTATE_MCLK_LEVEL &&
soc_table->count > SMU_13_0_6_UMD_PSTATE_SOCCLK_LEVEL) {
@@@ -1398,7 -1409,15 +1409,15 @@@ static int smu_v13_0_6_emit_clk_levels(
pstate_table->uclk_pstate.curr.min,
pstate_table->uclk_pstate.curr.max);
break;
+ case SMU_OD_FCLK:
+ if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT))
+ return -EOPNOTSUPP;
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_FCLK");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ pstate_table->fclk_pstate.curr.min,
+ pstate_table->fclk_pstate.curr.max);
+ break;
case SMU_SCLK:
case SMU_GFXCLK:
single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
@@@ -2040,7 -2059,7 +2059,7 @@@ static int smu_v13_0_6_set_soft_freq_li
int ret = 0;
if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK &&
- clk_type != SMU_UCLK)
+ clk_type != SMU_UCLK && clk_type != SMU_FCLK)
return -EINVAL;
if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) &&
@@@ -2081,6 -2100,15 +2100,15 @@@
pstate_table->uclk_pstate.curr.max = max;
}
+ if (clk_type == SMU_FCLK) {
+ if (max == pstate_table->fclk_pstate.curr.max)
+ return 0;
+
+ ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_FCLK, 0, max, false);
+ if (!ret)
+ pstate_table->fclk_pstate.curr.max = max;
+ }
+
return ret;
}
@@@ -2123,6 -2151,7 +2151,7 @@@ static int smu_v13_0_6_usr_edit_dpm_tab
struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
struct smu_dpm_table *uclk_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
uint32_t min_clk;
uint32_t max_clk;
@@@ -2203,6 -2232,40 +2232,40 @@@
pstate_table->uclk_pstate.custom.max = input[1];
}
break;
+ case PP_OD_EDIT_FCLK_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (!smu_cmn_feature_is_enabled(smu,
+ SMU_FEATURE_DPM_FCLK_BIT)) {
+ dev_warn(smu->adev->dev,
+ "FCLK limits setting not supported!\n");
+ return -EOPNOTSUPP;
+ }
+
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.fclk_table);
+ if (input[0] == 0) {
+ dev_info(smu->adev->dev,
+ "Setting min FCLK level is not supported\n");
+ return -EOPNOTSUPP;
+ } else if (input[0] == 1) {
+ if (input[1] > max_clk) {
+ dev_warn(smu->adev->dev,
+ "Maximum FCLK (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
+ input[1], max_clk);
+ pstate_table->fclk_pstate.custom.max =
+ pstate_table->fclk_pstate.curr.max;
+ return -EINVAL;
+ }
+
+ pstate_table->fclk_pstate.custom.max = input[1];
+ } else {
+ return -EINVAL;
+ }
+ break;
case PP_OD_RESTORE_DEFAULT_TABLE:
if (size != 0) {
@@@ -2232,6 -2295,17 +2295,17 @@@
if (ret)
return ret;
}
+
+ if (SMU_DPM_TABLE_MAX(fclk_table) !=
+ pstate_table->fclk_pstate.curr.max) {
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.fclk_table);
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.fclk_table);
+ ret = smu_v13_0_6_set_soft_freq_limited_range(smu,
+ SMU_FCLK, min_clk,
+ max_clk, false);
+ if (ret)
+ return ret;
+ }
smu_v13_0_reset_custom_level(smu);
}
break;
@@@ -2258,6 -2332,16 +2332,16 @@@
if (ret)
return ret;
+ if (pstate_table->fclk_pstate.custom.max) {
+ min_clk = pstate_table->fclk_pstate.curr.min;
+ max_clk = pstate_table->fclk_pstate.custom.max;
+ ret = smu_v13_0_6_set_soft_freq_limited_range(smu,
+ SMU_FCLK, min_clk,
+ max_clk, false);
+ if (ret)
+ return ret;
+ }
+
if (!pstate_table->uclk_pstate.custom.max)
return 0;
@@@ -3163,14 -3247,25 +3247,25 @@@ static int smu_v13_0_6_reset_vcn(struc
static int smu_v13_0_6_ras_send_msg(struct smu_context *smu, enum smu_message_type msg, uint32_t param, uint32_t *read_arg)
{
+ struct amdgpu_device *adev = smu->adev;
int ret;
+ if (amdgpu_sriov_vf(adev))
+ return -EOPNOTSUPP;
+
switch (msg) {
case SMU_MSG_QueryValidMcaCount:
case SMU_MSG_QueryValidMcaCeCount:
case SMU_MSG_McaBankDumpDW:
case SMU_MSG_McaBankCeDumpDW:
case SMU_MSG_ClearMcaOnRead:
+ case SMU_MSG_GetRASTableVersion:
+ case SMU_MSG_GetBadPageCount:
+ case SMU_MSG_GetBadPageMcaAddr:
+ case SMU_MSG_SetTimestamp:
+ case SMU_MSG_GetTimestamp:
+ case SMU_MSG_GetBadPageIpid:
+ case SMU_MSG_EraseRasTable:
ret = smu_cmn_send_smc_msg_with_param(smu, msg, param, read_arg);
break;
default:
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-03-09 14:35 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-03-09 14:35 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Linux Kernel Mailing List, Linux Next Mailing List,
Sunil Khatri
[-- Attachment #1: Type: text/plain, Size: 983 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
between commit:
65b5c326ce410 ("drm/amdgpu/userq: refcount userqueues to avoid any race conditions")
from the drm-fixes tree and commit:
4952189b284d4 ("drm/amdgpu/userq: refcount userqueues to avoid any race conditions")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 5239b06b9ab03,d8ce7b3733e75..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-03-06 13:47 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-03-06 13:47 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Kernel Mailing List, Linux Next Mailing List,
Michal Wajdeczko, Rodrigo Vivi, Tomasz Lis
[-- Attachment #1: Type: text/plain, Size: 979 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/xe/xe_exec_queue.c
between commit:
99f9b5343cae8 ("drm/xe/queue: Call fini on exec queue creation fail")
from the drm-fixes tree and commits:
393e5fea6f7d7 ("drm/xe/queue: Call fini on exec queue creation fail")
ec172c7befc4a ("drm/xe: Wrappers for setting and getting LRC references")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/xe/xe_exec_queue.c
index 8ecdf949f9e4c,2d0e73a6a6eee..0000000000000
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-01-30 15:37 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-01-30 15:37 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Brian Nguyen, Linux Kernel Mailing List, Linux Next Mailing List,
Lukasz Laguna, Matthew Brost, Matt Roper, Michal Wajdeczko,
Nitin Gote, Oak Zeng, Tejas Upadhyay, Thomas Hellström
[-- Attachment #1: Type: text/plain, Size: 3823 bytes --]
Hi all,
Today's linux-next merge of the drm tree got conflicts in:
drivers/gpu/drm/xe/xe_pci.c
drivers/gpu/drm/xe/xe_pci_types.h
between commit:
ca8dcfedac480 ("drm/xe: derive mem copy capability from graphics version")
from the drm-fixes tree and commits:
83f4151787c5d ("drm/xe/lnl: Drop pre-production workaround support")
7ef2d25e47736 ("drm/xe: Track pre-production workaround support")
9b1a0e0a15c97 ("drm/xe: Add page reclamation info to device info")
79cb005c71343 ("drm/xe: Add device flag to indicate standalone MERT")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/xe/xe_pci.c
index 2aa883f5ef797,09189ff3da441..0000000000000
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@@ -358,10 -365,15 +364,14 @@@ static const struct xe_device_desc bmg_
.has_fan_control = true,
.has_flat_ccs = 1,
.has_mbx_power_limits = true,
+ .has_mbx_thermal_info = true,
.has_gsc_nvm = 1,
.has_heci_cscfi = 1,
+ .has_i2c = true,
.has_late_bind = true,
+ .has_pre_prod_wa = 1,
+ .has_soc_remapper_telem = true,
.has_sriov = true,
- .has_mem_copy_instr = true,
.max_gt_per_tile = 2,
.needs_scratch = true,
.subplatforms = (const struct xe_subplatform_desc[]) {
@@@ -378,6 -390,9 +388,8 @@@ static const struct xe_device_desc ptl_
.has_display = true,
.has_flat_ccs = 1,
.has_sriov = true,
- .has_mem_copy_instr = true,
+ .has_pre_prod_wa = 1,
+ .has_pxp = true,
.max_gt_per_tile = 2,
.needs_scratch = true,
.needs_shared_vf_gt_wq = true,
@@@ -390,6 -405,8 +402,7 @@@ static const struct xe_device_desc nvls
.dma_mask_size = 46,
.has_display = true,
.has_flat_ccs = 1,
- .has_mem_copy_instr = true,
+ .has_pre_prod_wa = 1,
.max_gt_per_tile = 2,
.require_force_probe = true,
.va_bits = 48,
@@@ -666,11 -692,18 +688,17 @@@ static int xe_info_init_early(struct xe
xe->info.has_gsc_nvm = desc->has_gsc_nvm;
xe->info.has_heci_gscfi = desc->has_heci_gscfi;
xe->info.has_heci_cscfi = desc->has_heci_cscfi;
+ xe->info.has_i2c = desc->has_i2c;
xe->info.has_late_bind = desc->has_late_bind;
xe->info.has_llc = desc->has_llc;
+ xe->info.has_mert = desc->has_mert;
+ xe->info.has_page_reclaim_hw_assist = desc->has_page_reclaim_hw_assist;
+ xe->info.has_pre_prod_wa = desc->has_pre_prod_wa;
xe->info.has_pxp = desc->has_pxp;
+ xe->info.has_soc_remapper_sysctrl = desc->has_soc_remapper_sysctrl;
+ xe->info.has_soc_remapper_telem = desc->has_soc_remapper_telem;
xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) &&
desc->has_sriov;
- xe->info.has_mem_copy_instr = desc->has_mem_copy_instr;
xe->info.skip_guc_pc = desc->skip_guc_pc;
xe->info.skip_mtcfg = desc->skip_mtcfg;
xe->info.skip_pcode = desc->skip_pcode;
diff --cc drivers/gpu/drm/xe/xe_pci_types.h
index a4451bdc79fb3,20acc5349ee6d..0000000000000
--- a/drivers/gpu/drm/xe/xe_pci_types.h
+++ b/drivers/gpu/drm/xe/xe_pci_types.h
@@@ -46,7 -48,14 +48,13 @@@ struct xe_device_desc
u8 has_late_bind:1;
u8 has_llc:1;
u8 has_mbx_power_limits:1;
+ u8 has_mbx_thermal_info:1;
- u8 has_mem_copy_instr:1;
+ u8 has_mert:1;
+ u8 has_pre_prod_wa:1;
+ u8 has_page_reclaim_hw_assist:1;
u8 has_pxp:1;
+ u8 has_soc_remapper_sysctrl:1;
+ u8 has_soc_remapper_telem:1;
u8 has_sriov:1;
u8 needs_scratch:1;
u8 skip_guc_pc:1;
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-01-30 15:28 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-01-30 15:28 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Jack Xiao, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 3625 bytes --]
Hi all,
Today's linux-next merge of the drm tree got conflicts in:
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
between commits:
3eb46fbb601f9 ("drm/amdgpu/gfx11: adjust KGQ reset sequence")
dfd64f6e8cd7b ("drm/amdgpu/gfx12: adjust KGQ reset sequence")
from the drm-fixes tree and commit:
d09c7e266c8cd ("drm/amdgpu/mes: add multi-xcc support")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index e642236ea2c51,3a4ca104b1612..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@@ -6828,7 -6832,7 +6833,7 @@@ static int gfx_v11_0_reset_kgq(struct a
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
- r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, use_mmio);
- r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false, 0);
++ r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, use_mmio, 0);
if (r) {
dev_warn(adev->dev, "reset via MES failed and try pipe reset %d\n", r);
@@@ -6837,18 -6841,16 +6842,18 @@@
return r;
}
- r = gfx_v11_0_kgq_init_queue(ring, true);
- if (r) {
- dev_err(adev->dev, "failed to init kgq\n");
- return r;
- }
+ if (use_mmio) {
+ r = gfx_v11_0_kgq_init_queue(ring, true);
+ if (r) {
+ dev_err(adev->dev, "failed to init kgq\n");
+ return r;
+ }
- r = amdgpu_mes_map_legacy_queue(adev, ring);
- r = amdgpu_mes_map_legacy_queue(adev, ring, 0);
- if (r) {
- dev_err(adev->dev, "failed to remap kgq\n");
- return r;
++ r = amdgpu_mes_map_legacy_queue(adev, ring, 0);
+ if (r) {
+ dev_err(adev->dev, "failed to remap kgq\n");
+ return r;
+ }
}
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
diff --cc drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index 4aab89a9ab401,40660b05f9794..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@@ -5302,7 -5296,7 +5297,7 @@@ static int gfx_v12_0_reset_kgq(struct a
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
- r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, use_mmio);
- r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false, 0);
++ r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, use_mmio, 0);
if (r) {
dev_warn(adev->dev, "reset via MES failed and try pipe reset %d\n", r);
r = gfx_v12_reset_gfx_pipe(ring);
@@@ -5310,18 -5304,16 +5305,18 @@@
return r;
}
- r = gfx_v12_0_kgq_init_queue(ring, true);
- if (r) {
- dev_err(adev->dev, "failed to init kgq\n");
- return r;
- }
+ if (use_mmio) {
+ r = gfx_v12_0_kgq_init_queue(ring, true);
+ if (r) {
+ dev_err(adev->dev, "failed to init kgq\n");
+ return r;
+ }
- r = amdgpu_mes_map_legacy_queue(adev, ring);
- r = amdgpu_mes_map_legacy_queue(adev, ring, 0);
- if (r) {
- dev_err(adev->dev, "failed to remap kgq\n");
- return r;
++ r = amdgpu_mes_map_legacy_queue(adev, ring, 0);
+ if (r) {
+ dev_err(adev->dev, "failed to remap kgq\n");
+ return r;
+ }
}
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2026-01-23 17:45 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2026-01-23 17:45 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Kernel Mailing List, Linux Next Mailing List,
Thomas Hellström
[-- Attachment #1: Type: text/plain, Size: 4640 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
include/drm/drm_pagemap.h
between commits:
754c232384386 ("drm/pagemap, drm/xe: Ensure that the devmem allocation is idle before use")
bdcdf968be314 ("drm, drm/xe: Fix xe userptr in the absence of CONFIG_DEVICE_PRIVATE")
from the drm-fixes tree and commits:
a599b98607dec ("drm/pagemap, drm/xe: Add refcounting to struct drm_pagemap")
75af93b3f5d0a ("drm/pagemap, drm/xe: Support destination migration over interconnect")
77f14f2f2d73f ("drm/pagemap: Add a drm_pagemap cache and shrinker")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc include/drm/drm_pagemap.h
index eb29e5309f0ab,46e9c58f09e01..0000000000000
--- a/include/drm/drm_pagemap.h
+++ b/include/drm/drm_pagemap.h
@@@ -209,19 -243,56 +243,69 @@@ struct drm_pagemap_devmem_ops
struct dma_fence *pre_migrate_fence);
};
+#if IS_ENABLED(CONFIG_ZONE_DEVICE)
+
+struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page);
+
+#else
+
+static inline struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page)
+{
+ return NULL;
+}
+
+#endif /* IS_ENABLED(CONFIG_ZONE_DEVICE) */
+
+ int drm_pagemap_init(struct drm_pagemap *dpagemap,
+ struct dev_pagemap *pagemap,
+ struct drm_device *drm,
+ const struct drm_pagemap_ops *ops);
+
+ struct drm_pagemap *drm_pagemap_create(struct drm_device *drm,
+ struct dev_pagemap *pagemap,
+ const struct drm_pagemap_ops *ops);
+
+ #if IS_ENABLED(CONFIG_DRM_GPUSVM)
+
+ void drm_pagemap_put(struct drm_pagemap *dpagemap);
+
+ #else
+
+ static inline void drm_pagemap_put(struct drm_pagemap *dpagemap)
+ {
+ }
+
+ #endif /* IS_ENABLED(CONFIG_DRM_GPUSVM) */
+
+ /**
+ * drm_pagemap_get() - Obtain a reference on a struct drm_pagemap
+ * @dpagemap: Pointer to the struct drm_pagemap, or NULL.
+ *
+ * Return: Pointer to the struct drm_pagemap, or NULL.
+ */
+ static inline struct drm_pagemap *
+ drm_pagemap_get(struct drm_pagemap *dpagemap)
+ {
+ if (likely(dpagemap))
+ kref_get(&dpagemap->ref);
+
+ return dpagemap;
+ }
+
+ /**
+ * drm_pagemap_get_unless_zero() - Obtain a reference on a struct drm_pagemap
+ * unless the current reference count is zero.
+ * @dpagemap: Pointer to the drm_pagemap or NULL.
+ *
+ * Return: A pointer to @dpagemap if the reference count was successfully
+ * incremented. NULL if @dpagemap was NULL, or its refcount was 0.
+ */
+ static inline struct drm_pagemap * __must_check
+ drm_pagemap_get_unless_zero(struct drm_pagemap *dpagemap)
+ {
+ return (dpagemap && kref_get_unless_zero(&dpagemap->ref)) ? dpagemap : NULL;
+ }
+
/**
* struct drm_pagemap_devmem - Structure representing a GPU SVM device memory allocation
*
@@@ -246,8 -317,23 +330,25 @@@ struct drm_pagemap_devmem
struct dma_fence *pre_migrate_fence;
};
+ /**
+ * struct drm_pagemap_migrate_details - Details to govern migration.
+ * @timeslice_ms: The time requested for the migrated pagemap pages to
+ * be present in @mm before being allowed to be migrated back.
+ * @can_migrate_same_pagemap: Whether the copy function as indicated by
+ * the @source_peer_migrates flag, can migrate device pages within a
+ * single drm_pagemap.
+ * @source_peer_migrates: Whether on p2p migration, The source drm_pagemap
+ * should use the copy_to_ram() callback rather than the destination
+ * drm_pagemap should use the copy_to_devmem() callback.
+ */
+ struct drm_pagemap_migrate_details {
+ unsigned long timeslice_ms;
+ u32 can_migrate_same_pagemap : 1;
+ u32 source_peer_migrates : 1;
+ };
+
+#if IS_ENABLED(CONFIG_ZONE_DEVICE)
+
int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
struct mm_struct *mm,
unsigned long start, unsigned long end,
@@@ -269,6 -356,7 +369,10 @@@ int drm_pagemap_populate_mm(struct drm_
struct mm_struct *mm,
unsigned long timeslice_ms);
+#endif /* IS_ENABLED(CONFIG_ZONE_DEVICE) */
+
+ void drm_pagemap_destroy(struct drm_pagemap *dpagemap, bool is_atomic_or_reclaim);
+
+ int drm_pagemap_reinit(struct drm_pagemap *dpagemap);
++
#endif
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2025-06-27 2:58 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2025-06-27 2:58 UTC (permalink / raw)
To: Dave Airlie
Cc: DRI, Linux Kernel Mailing List, Linux Next Mailing List,
Maarten Lankhorst, Michal Wajdeczko, Thomas Hellström
[-- Attachment #1: Type: text/plain, Size: 2103 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/xe/xe_ggtt.c
between commit:
af2b588abe00 ("drm/xe: Process deferred GGTT node removals on device unwind")
from the drm-fixes tree and commit:
b2d6fd7ac598 ("drm/xe: Do not rely on GGTT internals in xe_guc_buf kunit tests")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/gpu/drm/xe/xe_ggtt.c
index 2c799958c1e4,7b11fa1356f0..000000000000
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@@ -201,13 -222,22 +222,29 @@@ static const struct xe_ggtt_pt_ops xelp
.ggtt_set_pte = xe_ggtt_set_pte_and_flush,
};
+static void dev_fini_ggtt(void *arg)
+{
+ struct xe_ggtt *ggtt = arg;
+
+ drain_workqueue(ggtt->wq);
+}
+
+ static void __xe_ggtt_init_early(struct xe_ggtt *ggtt, u32 reserved)
+ {
+ drm_mm_init(&ggtt->mm, reserved,
+ ggtt->size - reserved);
+ mutex_init(&ggtt->lock);
+ primelockdep(ggtt);
+ }
+
+ int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 reserved, u32 size)
+ {
+ ggtt->size = size;
+ __xe_ggtt_init_early(ggtt, reserved);
+ return 0;
+ }
+ EXPORT_SYMBOL_IF_KUNIT(xe_ggtt_init_kunit);
+
/**
* xe_ggtt_init_early - Early GGTT initialization
* @ggtt: the &xe_ggtt to be initialized
@@@ -264,12 -290,8 +297,12 @@@ int xe_ggtt_init_early(struct xe_ggtt *
if (err)
return err;
+ err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt);
+ if (err)
+ return err;
+
if (IS_SRIOV_VF(xe)) {
- err = xe_gt_sriov_vf_prepare_ggtt(xe_tile_get_gt(ggtt->tile, 0));
+ err = xe_tile_sriov_vf_prepare_ggtt(ggtt->tile);
if (err)
return err;
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2024-10-18 1:56 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2024-10-18 1:56 UTC (permalink / raw)
To: Dave Airlie
Cc: Ankit Nautiyal, Imre Deak, Joonas Lahtinen, DRI,
Linux Kernel Mailing List, Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 1814 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/i915/display/intel_dp_mst.c
between commit:
69b3d8721267 ("drm/i915/dp_mst: Handle error during DSC BW overhead/slice calculation")
from the drm-fixes tree and commit:
f2e2092a979c ("drm/i915/display: Use joined pipes in dsc helpers for slices, bpp")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/gpu/drm/i915/display/intel_dp_mst.c
index eeaedd979354,4765bda154c1..000000000000
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@@ -147,19 -156,6 +148,19 @@@ static int intel_dp_mst_calc_pbn(int pi
return DIV_ROUND_UP(effective_data_rate * 64, 54 * 1000);
}
+static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connector,
+ const struct intel_crtc_state *crtc_state)
+{
+ const struct drm_display_mode *adjusted_mode =
+ &crtc_state->hw.adjusted_mode;
- int num_joined_pipes = crtc_state->joiner_pipes;
++ int num_joined_pipes = intel_crtc_num_joined_pipes(crtc_state);
+
+ return intel_dp_dsc_get_slice_count(connector,
+ adjusted_mode->clock,
+ adjusted_mode->hdisplay,
+ num_joined_pipes);
+}
+
static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
int max_bpp,
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2024-06-27 15:08 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2024-06-27 15:08 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Lijo Lazar, Li Ma, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 1325 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
between commit:
c223376b3019a ("drm/amd/swsmu: add MALL init support workaround for smu_v14_0_1")
from the drm-fixes tree and commit:
ec41bdd82e9b0 ("drm/amd/pm: Update PMFW messages for SMUv13.0.6")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index 2e32b085824ae,12a7b0634ed56..0000000000000
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@@ -272,7 -272,8 +272,8 @@@
__SMU_DUMMY_MAP(SetSoftMinVpe), \
__SMU_DUMMY_MAP(GetMetricsVersion), \
__SMU_DUMMY_MAP(EnableUCLKShadow), \
- __SMU_DUMMY_MAP(RmaDueToBadPageThreshold),\
+ __SMU_DUMMY_MAP(RmaDueToBadPageThreshold), \
+ __SMU_DUMMY_MAP(SelectPstatePolicy), \
__SMU_DUMMY_MAP(MALLPowerController), \
__SMU_DUMMY_MAP(MALLPowerState),
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2024-06-27 15:00 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2024-06-27 15:00 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Frank Min, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 947 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
between commit:
f6f49dda49db7 ("drm/amdgpu/atomfirmware: fix parsing of vram_info")
from the drm-fixes tree and commit:
9a55c77978308 ("drm/amdgpu: fix getting vram info for gfx12")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index 2e13c7c4b2b41,f932bec6e5345..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2024-06-21 13:21 Mark Brown
0 siblings, 0 replies; 41+ messages in thread
From: Mark Brown @ 2024-06-21 13:21 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Dillon Varone, Linux Kernel Mailing List,
Linux Next Mailing List, Michael Strauss, Nicholas Kazlauskas
[-- Attachment #1: Type: text/plain, Size: 1772 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
between commit:
c03d770c0b014 ("drm/amd/display: Attempt to avoid empty TUs when endpoint is DPIA")
from the drm-fixes tree and commits:
47745acc5e8dd ("drm/amd/display: Add trigger FIFO resync path for DCN35")
0127f0445f7c1 ("drm/amd/display: Refactor input mode programming for DIG FIFO")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
index 199781233fd5f..30e6a63988391 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
@@ -157,8 +160,8 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
.set_mcm_luts = dcn32_set_mcm_luts,
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
- .set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
- .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy,
+ .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio,
+ .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
.dsc_pg_control = dcn35_dsc_pg_control,
.dsc_pg_status = dcn32_dsc_pg_status,
.enable_plane = dcn35_enable_plane,
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2023-08-18 1:53 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2023-08-18 1:53 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Evan Quan, Kenneth Feng, Linux Kernel Mailing List,
Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 1803 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
between commits:
61319b8e3b58 ("drm/amd/pm: disable the SMU13 OD feature support temporarily")
b6360a5ec31d ("drm/amd/pm: disallow the fan setting if there is no fan on smu 13.0.0")
from the drm-fixes tree and commit:
510d242f498a ("drm/amd/pm: disable the SMU13 OD feature support temporarily")
from the drm tree.
The git automatic resolution got this wrong by adding an extra "#if 0"
above the duplicated "PPTable_t *pptable = smu->smu_table.driver_pptable;"
from b6360a5ec31d.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 0fb6be11a0cc,fddcd834bcec..000000000000
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@@ -331,9 -331,8 +331,8 @@@ static int smu_v13_0_0_check_powerplay_
struct smu_13_0_0_powerplay_table *powerplay_table =
table_context->power_play_table;
struct smu_baco_context *smu_baco = &smu->smu_baco;
-#if 0
PPTable_t *pptable = smu->smu_table.driver_pptable;
+#if 0
- PPTable_t *pptable = smu->smu_table.driver_pptable;
const OverDriveLimits_t * const overdrive_upperlimits =
&pptable->SkuTable.OverDriveLimitsBasicMax;
const OverDriveLimits_t * const overdrive_lowerlimits =
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2023-02-13 0:23 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2023-02-13 0:23 UTC (permalink / raw)
To: Dave Airlie
Cc: DRI, Alex Deucher, Linux Kernel Mailing List, Linux Next Mailing List
[-- Attachment #1: Type: text/plain, Size: 1571 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
between commits:
877f26bf3ca6 ("drm/amd/display: disable S/G display on DCN 2.1.0")
077e9659581a ("drm/amd/display: disable S/G display on DCN 3.1.2/3")
7ece674cd946 ("Revert "drm/amd/display: disable S/G display on DCN 3.1.4"")
9734a75cd99d ("Revert "drm/amd/display: disable S/G display on DCN 3.1.2/3"")
1b7ac7989ad8 ("Revert "drm/amd/display: disable S/G display on DCN 2.1.0"")
e7d636476ba7 ("Revert "drm/amd/display: disable S/G display on DCN 3.1.5"")
from the drm-fixes tree and commits:
2404f9b0ea01 ("drm/amd/display: disable S/G display on DCN 2.1.0")
f081cd4ca265 ("drm/amd/display: disable S/G display on DCN 3.1.2/3")
69ed0c5d44d7 ("Revert "drm/amd/display: disable S/G display on DCN 3.1.4"")
from the drm tree.
Git's automatic merge ignored commit 1b7ac7989ad8, since on the HEAD
side it was cancelled out by commit 877f26bf3ca6. So I have to manually
reapply commit 1b7ac7989ad8.
This is an issue with duplicate patches that you need to keep in mind.
I fixed it up (I used the former changes) and can carry the fix as
necessary. This is now fixed as far as linux-next is concerned, but any
non trivial conflicts should be mentioned to your upstream maintainer
when your tree is submitted for merging. You may also want to consider
cooperating with the maintainer of the conflicting tree to minimise any
particularly complex conflicts.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2022-09-26 17:49 broonie
0 siblings, 0 replies; 41+ messages in thread
From: broonie @ 2022-09-26 17:49 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Alvin Lee, Lee, Linux Kernel Mailing List,
Linux Next Mailing List
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
between commit:
58d97c99c99f4 ("drm/amd/display: Update MBLK calculation for SubVP")
from the drm-fixes tree and commits:
41c81dcf59991 ("drm/amd/display: Update MBLK calculation for SubVP")
5c1a431aaf52b ("drm/amd/display: Added debug option for forcing subvp num ways")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
index 1f195c5b3377d,417dfdcf95962..0000000000000
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2022-02-25 16:37 broonie
0 siblings, 0 replies; 41+ messages in thread
From: broonie @ 2022-02-25 16:37 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Daniel Vetter, Guchun Chen, Leslie Shi,
Linux Kernel Mailing List, Linux Next Mailing List,
Tomohito Esaki
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
between commit:
e2b993302f40c ("drm/amdgpu: bypass tiling flag check in virtual display case (v2)")
from the drm-fixes tree and commit:
2af104290da5e ("drm: introduce fb_modifiers_not_supported flag in mode_config")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index c4387b38229c2,9e5fc4cdb8ec9..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@@ -1141,7 -1148,7 +1148,7 @@@ int amdgpu_display_framebuffer_init(str
if (ret)
return ret;
- if (!dev->mode_config.allow_fb_modifiers && !adev->enable_virtual_display) {
- if (dev->mode_config.fb_modifiers_not_supported) {
++ if (dev->mode_config.fb_modifiers_not_supported && !adev->enable_virtual_display) {
drm_WARN_ONCE(dev, adev->family >= AMDGPU_FAMILY_AI,
"GFX9+ requires FB check based on format modifier\n");
ret = check_tiling_flags_gfx6(rfb);
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2022-02-24 16:33 broonie
0 siblings, 0 replies; 41+ messages in thread
From: broonie @ 2022-02-24 16:33 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Linux Kernel Mailing List, Linux Next Mailing List,
Nicholas Kazlauskas, Wenjing Liu
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
between commit:
3743e7f6fcb93 ("drm/amd/display: Fix stream->link_enc unassigned during stream removal")
from the drm-fixes tree and commits:
6d33f0e820bfb ("drm/amd/display: Fix stream->link_enc unassigned during stream removal")
d9eb8fea6862e ("drm/amd/display: Drop DCN for DP2.x logic")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 18757c1585232,19b56f9acf84e..0000000000000
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
[Used drm version]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2021-08-06 12:04 Mark Brown
2021-08-10 11:56 ` Geert Uytterhoeven
0 siblings, 1 reply; 41+ messages in thread
From: Mark Brown @ 2021-08-06 12:04 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Alex Deucher, Linux Kernel Mailing List, Linux Next Mailing List,
Chengming Gui, Tao Zhou
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
between commit:
e00f543d3596 ("drm/amdgpu: add DID for beige goby")
from the drm-fixes tree and commit:
a8f706966b92 ("drm/amdgpu: add pci device id for cyan_skillfish")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 5ed8381ae0f5,d637b0536f84..000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@@ -1213,13 -1212,9 +1212,16 @@@ static const struct pci_device_id pciid
{0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
{0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
+ /* BEIGE_GOBY */
+ {0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+ {0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+ {0x1002, 0x7422, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+ {0x1002, 0x7423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+ {0x1002, 0x743F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+
+ /* CYAN_SKILLFISH */
+ {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
+
{0, 0, 0}
};
^ permalink raw reply [flat|nested] 41+ messages in thread* Re: linux-next: manual merge of the drm tree with the drm-fixes tree
2021-08-06 12:04 Mark Brown
@ 2021-08-10 11:56 ` Geert Uytterhoeven
2021-08-10 12:53 ` Stephen Rothwell
0 siblings, 1 reply; 41+ messages in thread
From: Geert Uytterhoeven @ 2021-08-10 11:56 UTC (permalink / raw)
To: Mark Brown, Stephen Rothwell
Cc: Dave Airlie, DRI, Alex Deucher, Linux Kernel Mailing List,
Linux Next Mailing List, Chengming Gui, Tao Zhou
Hi Mark, Stephen,
On Fri, Aug 6, 2021 at 6:11 PM Mark Brown <broonie@kernel.org> wrote:
> Today's linux-next merge of the drm tree got a conflict in:
>
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>
> between commit:
>
> e00f543d3596 ("drm/amdgpu: add DID for beige goby")
>
> from the drm-fixes tree and commit:
>
> a8f706966b92 ("drm/amdgpu: add pci device id for cyan_skillfish")
>
> from the drm tree.
>
> I fixed it up (see below) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging. You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
> complex conflicts.
>
>
> diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 5ed8381ae0f5,d637b0536f84..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@@ -1213,13 -1212,9 +1212,16 @@@ static const struct pci_device_id pciid
> {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
> {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
>
> + /* BEIGE_GOBY */
> + {0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> + {0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> + {0x1002, 0x7422, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> + {0x1002, 0x7423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> + {0x1002, 0x743F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> +
> + /* CYAN_SKILLFISH */
> + {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
> +
> {0, 0, 0}
> };
next-20210806 and later have a different resolution, duplicating the
BEIGE_GOBY entries before and after the CYAN_SKILLFISH entry.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 41+ messages in thread* Re: linux-next: manual merge of the drm tree with the drm-fixes tree
2021-08-10 11:56 ` Geert Uytterhoeven
@ 2021-08-10 12:53 ` Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2021-08-10 12:53 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Mark Brown, Dave Airlie, DRI, Alex Deucher,
Linux Kernel Mailing List, Linux Next Mailing List,
Chengming Gui, Tao Zhou
[-- Attachment #1: Type: text/plain, Size: 2102 bytes --]
Hi Geert,
On Tue, 10 Aug 2021 13:56:12 +0200 Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>
> On Fri, Aug 6, 2021 at 6:11 PM Mark Brown <broonie@kernel.org> wrote:
> > Today's linux-next merge of the drm tree got a conflict in:
> >
> > drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> >
> > between commit:
> >
> > e00f543d3596 ("drm/amdgpu: add DID for beige goby")
> >
> > from the drm-fixes tree and commit:
> >
> > a8f706966b92 ("drm/amdgpu: add pci device id for cyan_skillfish")
> >
> > from the drm tree.
> >
> >
> > diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > index 5ed8381ae0f5,d637b0536f84..000000000000
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > @@@ -1213,13 -1212,9 +1212,16 @@@ static const struct pci_device_id pciid
> > {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
> > {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
> >
> > + /* BEIGE_GOBY */
> > + {0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> > + {0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> > + {0x1002, 0x7422, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> > + {0x1002, 0x7423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> > + {0x1002, 0x743F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
> > +
> > + /* CYAN_SKILLFISH */
> > + {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
> > +
> > {0, 0, 0}
> > };
>
> next-20210806 and later have a different resolution, duplicating the
> BEIGE_GOBY entries before and after the CYAN_SKILLFISH entry.
That's because commit e00f543d3596 (which is now in Linus' tree) has
been copied (as a separate commit) into the amdgpu tree (where the
CYAN_SKILLFISH change is present, with the BEIGE_GOBY change after
that).
I have dropped the current rerere resolution and will redo the
resolution tomorrow.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread
* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2020-07-10 2:28 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2020-07-10 2:28 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Next Mailing List, Linux Kernel Mailing List, Huang Rui,
Emily Deng, Alex Deucher
[-- Attachment #1: Type: text/plain, Size: 1754 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
between commit:
c564b8601ae9 ("drm/amdgpu: add TMR destory function for psp")
from the drm-fixes tree and commit:
3bda8acd974e ("drm/amdgpu/sriov: Add clear vf fw support")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index ef3269c43d4f,9342a9e8cadf..000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@@ -1825,6 -1866,9 +1912,7 @@@ static int psp_hw_fini(void *handle
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct psp_context *psp = &adev->psp;
- void *tmr_buf;
- void **pptr;
+ int ret;
if (psp->adev->psp.ta_fw) {
psp_ras_terminate(psp);
@@@ -1833,10 -1877,16 +1921,15 @@@
}
psp_asd_unload(psp);
+ ret = psp_clear_vf_fw(psp);
+ if (ret) {
+ DRM_ERROR("PSP clear vf fw!\n");
+ return ret;
+ }
+ psp_tmr_terminate(psp);
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
- pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
- amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr);
amdgpu_bo_free_kernel(&psp->fw_pri_bo,
&psp->fw_pri_mc_addr, &psp->fw_pri_buf);
amdgpu_bo_free_kernel(&psp->fence_buf_bo,
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2019-08-23 3:20 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2019-08-23 3:20 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
Alexandre Courbot, CK Hu, Daniel Vetter
[-- Attachment #1: Type: text/plain, Size: 2181 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/mediatek/mtk_drm_drv.c
between commit:
4c6f3196e6ea ("drm/mediatek: use correct device to import PRIME buffers")
from the drm-fixes tree and commit:
3baeeb21983a ("drm/mtk: Drop drm_gem_prime_export/import")
from the drm tree.
I fixed it up (I think - see below) and can carry the fix as necessary.
This is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 7f5408cb2377,2ee809a6f3dc..000000000000
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@@ -351,21 -314,8 +345,20 @@@ static const struct file_operations mtk
.compat_ioctl = drm_compat_ioctl,
};
+/*
+ * We need to override this because the device used to import the memory is
+ * not dev->dev, as drm_gem_prime_import() expects.
+ */
+struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
+ struct dma_buf *dma_buf)
+{
+ struct mtk_drm_private *private = dev->dev_private;
+
+ return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
+}
+
static struct drm_driver mtk_drm_driver = {
- .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
- DRIVER_ATOMIC,
+ .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
.gem_free_object_unlocked = mtk_drm_gem_free_object,
.gem_vm_ops = &drm_gem_cma_vm_ops,
@@@ -373,8 -323,6 +366,7 @@@
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
- .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_import = mtk_drm_gem_prime_import,
.gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
.gem_prime_mmap = mtk_drm_gem_mmap_buf,
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2019-07-05 2:50 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2019-07-05 2:50 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
Trigger Huang, Alex Deucher
[-- Attachment #1: Type: text/plain, Size: 796 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
between commit:
25f09f858835 ("drm/amdgpu/gfx9: use reset default for PA_SC_FIFO_SIZE")
from the drm-fixes tree and commit:
1bff7f6c679f ("drm/amdgpu: RLC to program regs for Vega10 SR-IOV")
from the drm tree.
I fixed it up (the former removes the code modified by the latter) and
can carry the fix as necessary. This is now fixed as far as linux-next
is concerned, but any non trivial conflicts should be mentioned to your
upstream maintainer when your tree is submitted for merging. You may
also want to consider cooperating with the maintainer of the conflicting
tree to minimise any particularly complex conflicts.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2019-03-01 2:23 Stephen Rothwell
2019-03-01 23:29 ` Alex Deucher
0 siblings, 1 reply; 41+ messages in thread
From: Stephen Rothwell @ 2019-03-01 2:23 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
Mario Kleiner, David Francis, Alex Deucher
[-- Attachment #1: Type: text/plain, Size: 951 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
between commit:
d63716658ac1 ("drm/amd/display: Use vrr friendly pageflip throttling in DC.")
from the drm-fixes tree and commits:
8a48b44cd00f ("drm/amd/display: Call into DC once per multiplane flip")
bc7f670ee04c ("drm/amd/display: Perform plane updates only when needed")
from the drm tree.
I had no idea how to resolve this, so I just effectively reverted the
drm-fixes commit.
I fixed it up (see above) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* Re: linux-next: manual merge of the drm tree with the drm-fixes tree
2019-03-01 2:23 Stephen Rothwell
@ 2019-03-01 23:29 ` Alex Deucher
2019-03-04 0:54 ` Stephen Rothwell
0 siblings, 1 reply; 41+ messages in thread
From: Alex Deucher @ 2019-03-01 23:29 UTC (permalink / raw)
To: Stephen Rothwell
Cc: Dave Airlie, DRI, Alex Deucher, Linux Next Mailing List,
Linux Kernel Mailing List, David Francis
On Thu, Feb 28, 2019 at 9:24 PM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> Hi all,
>
> Today's linux-next merge of the drm tree got a conflict in:
>
> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>
> between commit:
>
> d63716658ac1 ("drm/amd/display: Use vrr friendly pageflip throttling in DC.")
>
> from the drm-fixes tree and commits:
>
> 8a48b44cd00f ("drm/amd/display: Call into DC once per multiplane flip")
> bc7f670ee04c ("drm/amd/display: Perform plane updates only when needed")
>
> from the drm tree.
>
> I had no idea how to resolve this, so I just effectively reverted the
> drm-fixes commit.
>
> I fixed it up (see above) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging. You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
> complex conflicts.
d63716658ac1 ("drm/amd/display: Use vrr friendly pageflip throttling
in DC.") should be reverted and this should be applied instead for
drm-next:
https://cgit.freedesktop.org/~agd5f/linux/commit/?h=drm-next-5.2-wip&id=5d5f43c235d02e4d8e9d50d012f3b21f380486eb
Alex
>
>
>
> --
> Cheers,
> Stephen Rothwell
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 41+ messages in thread* Re: linux-next: manual merge of the drm tree with the drm-fixes tree
2019-03-01 23:29 ` Alex Deucher
@ 2019-03-04 0:54 ` Stephen Rothwell
2019-03-11 12:36 ` Daniel Vetter
0 siblings, 1 reply; 41+ messages in thread
From: Stephen Rothwell @ 2019-03-04 0:54 UTC (permalink / raw)
To: Dave Airlie
Cc: Alex Deucher, DRI, Alex Deucher, Linux Next Mailing List,
Linux Kernel Mailing List, David Francis
[-- Attachment #1: Type: text/plain, Size: 1569 bytes --]
Hi Dave,
On Fri, 1 Mar 2019 18:29:58 -0500 Alex Deucher <alexdeucher@gmail.com> wrote:
>
> On Thu, Feb 28, 2019 at 9:24 PM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> >
> > Today's linux-next merge of the drm tree got a conflict in:
> >
> > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >
> > between commit:
> >
> > d63716658ac1 ("drm/amd/display: Use vrr friendly pageflip throttling in DC.")
> >
> > from the drm-fixes tree and commits:
> >
> > 8a48b44cd00f ("drm/amd/display: Call into DC once per multiplane flip")
> > bc7f670ee04c ("drm/amd/display: Perform plane updates only when needed")
> >
> > from the drm tree.
> >
> > I had no idea how to resolve this, so I just effectively reverted the
> > drm-fixes commit.
> >
> > I fixed it up (see above) and can carry the fix as necessary. This
> > is now fixed as far as linux-next is concerned, but any non trivial
> > conflicts should be mentioned to your upstream maintainer when your tree
> > is submitted for merging. You may also want to consider cooperating
> > with the maintainer of the conflicting tree to minimise any particularly
> > complex conflicts.
>
> d63716658ac1 ("drm/amd/display: Use vrr friendly pageflip throttling
> in DC.") should be reverted and this should be applied instead for
> drm-next:
> https://cgit.freedesktop.org/~agd5f/linux/commit/?h=drm-next-5.2-wip&id=5d5f43c235d02e4d8e9d50d012f3b21f380486eb
Maybe you should merge the drm-fixes tree into the drm tree and apply
the above ...
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* Re: linux-next: manual merge of the drm tree with the drm-fixes tree
2019-03-04 0:54 ` Stephen Rothwell
@ 2019-03-11 12:36 ` Daniel Vetter
0 siblings, 0 replies; 41+ messages in thread
From: Daniel Vetter @ 2019-03-11 12:36 UTC (permalink / raw)
To: Stephen Rothwell
Cc: Dave Airlie, David Francis, Linux Kernel Mailing List, DRI,
Alex Deucher, Linux Next Mailing List
On Mon, Mar 04, 2019 at 11:54:02AM +1100, Stephen Rothwell wrote:
> Hi Dave,
>
> On Fri, 1 Mar 2019 18:29:58 -0500 Alex Deucher <alexdeucher@gmail.com> wrote:
> >
> > On Thu, Feb 28, 2019 at 9:24 PM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> > >
> > > Today's linux-next merge of the drm tree got a conflict in:
> > >
> > > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > >
> > > between commit:
> > >
> > > d63716658ac1 ("drm/amd/display: Use vrr friendly pageflip throttling in DC.")
> > >
> > > from the drm-fixes tree and commits:
> > >
> > > 8a48b44cd00f ("drm/amd/display: Call into DC once per multiplane flip")
> > > bc7f670ee04c ("drm/amd/display: Perform plane updates only when needed")
> > >
> > > from the drm tree.
> > >
> > > I had no idea how to resolve this, so I just effectively reverted the
> > > drm-fixes commit.
> > >
> > > I fixed it up (see above) and can carry the fix as necessary. This
> > > is now fixed as far as linux-next is concerned, but any non trivial
> > > conflicts should be mentioned to your upstream maintainer when your tree
> > > is submitted for merging. You may also want to consider cooperating
> > > with the maintainer of the conflicting tree to minimise any particularly
> > > complex conflicts.
> >
> > d63716658ac1 ("drm/amd/display: Use vrr friendly pageflip throttling
> > in DC.") should be reverted and this should be applied instead for
> > drm-next:
> > https://cgit.freedesktop.org/~agd5f/linux/commit/?h=drm-next-5.2-wip&id=5d5f43c235d02e4d8e9d50d012f3b21f380486eb
>
> Maybe you should merge the drm-fixes tree into the drm tree and apply
> the above ...
Alex, can you pls get the amdgpu trees added to linux-next? From a quick
look those still seem to be missing.
Thanks, Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 41+ messages in thread
* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2018-12-14 1:51 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2018-12-14 1:51 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
Thomas Hellstrom, Christian König, Alex Deucher
[-- Attachment #1: Type: text/plain, Size: 4099 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
between commit:
fd567467753f ("drm/vmwgfx: Protect from excessive execbuf kernel memory allocations v3")
from the drm-fixes tree and commit:
a64f784bb14a ("drm/ttm: initialize globals during device init (v2)")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
index f88247046721,154eb09aa91e..000000000000
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
@@@ -42,93 -42,3 +42,39 @@@ int vmw_mmap(struct file *filp, struct
dev_priv = vmw_priv(file_priv->minor->dev);
return ttm_bo_mmap(filp, vma, &dev_priv->bdev);
}
+
- static int vmw_ttm_mem_global_init(struct drm_global_reference *ref)
- {
- DRM_INFO("global init.\n");
- return ttm_mem_global_init(ref->object);
- }
-
- static void vmw_ttm_mem_global_release(struct drm_global_reference *ref)
- {
- ttm_mem_global_release(ref->object);
- }
-
- int vmw_ttm_global_init(struct vmw_private *dev_priv)
- {
- struct drm_global_reference *global_ref;
- int ret;
-
- global_ref = &dev_priv->mem_global_ref;
- global_ref->global_type = DRM_GLOBAL_TTM_MEM;
- global_ref->size = sizeof(struct ttm_mem_global);
- global_ref->init = &vmw_ttm_mem_global_init;
- global_ref->release = &vmw_ttm_mem_global_release;
-
- ret = drm_global_item_ref(global_ref);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed setting up TTM memory accounting.\n");
- return ret;
- }
-
- dev_priv->bo_global_ref.mem_glob =
- dev_priv->mem_global_ref.object;
- global_ref = &dev_priv->bo_global_ref.ref;
- global_ref->global_type = DRM_GLOBAL_TTM_BO;
- global_ref->size = sizeof(struct ttm_bo_global);
- global_ref->init = &ttm_bo_global_init;
- global_ref->release = &ttm_bo_global_release;
- ret = drm_global_item_ref(global_ref);
-
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed setting up TTM buffer objects.\n");
- goto out_no_bo;
- }
-
- return 0;
- out_no_bo:
- drm_global_item_unref(&dev_priv->mem_global_ref);
- return ret;
- }
-
- void vmw_ttm_global_release(struct vmw_private *dev_priv)
- {
- drm_global_item_unref(&dev_priv->bo_global_ref.ref);
- drm_global_item_unref(&dev_priv->mem_global_ref);
- }
-
+/* struct vmw_validation_mem callback */
+static int vmw_vmt_reserve(struct vmw_validation_mem *m, size_t size)
+{
+ static struct ttm_operation_ctx ctx = {.interruptible = false,
+ .no_wait_gpu = false};
+ struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm);
+
+ return ttm_mem_global_alloc(vmw_mem_glob(dev_priv), size, &ctx);
+}
+
+/* struct vmw_validation_mem callback */
+static void vmw_vmt_unreserve(struct vmw_validation_mem *m, size_t size)
+{
+ struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm);
+
+ return ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+}
+
+/**
+ * vmw_validation_mem_init_ttm - Interface the validation memory tracker
+ * to ttm.
+ * @dev_priv: Pointer to struct vmw_private. The reason we choose a vmw private
+ * rather than a struct vmw_validation_mem is to make sure assumption in the
+ * callbacks that struct vmw_private derives from struct vmw_validation_mem
+ * holds true.
+ * @gran: The recommended allocation granularity
+ */
+void vmw_validation_mem_init_ttm(struct vmw_private *dev_priv, size_t gran)
+{
+ struct vmw_validation_mem *vvm = &dev_priv->vvm;
+
+ vvm->reserve_mem = vmw_vmt_reserve;
+ vvm->unreserve_mem = vmw_vmt_unreserve;
+ vvm->gran = gran;
+}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2018-12-07 2:38 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2018-12-07 2:38 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Next Mailing List, Linux Kernel Mailing List, Roman Li,
Alex Deucher, Dmytro Laktyushkin
[-- Attachment #1: Type: text/plain, Size: 853 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
between commit:
c6888879fd55 ("drm/amd/display: Fix 6x4K displays light-up on Vega20 (v2)")
from the drm-fixes tree and commit:
24f7dd7ea98d ("drm/amd/display: move pplib/smu notification to dccg block")
from the drm tree.
I fixed it up (I am not sure how to fix this up, so I just dropped the
drm-fixes change) and can carry the fix as necessary. This is now fixed
as far as linux-next is concerned, but any non trivial conflicts should
be mentioned to your upstream maintainer when your tree is submitted for
merging. You may also want to consider cooperating with the maintainer
of the conflicting tree to minimise any particularly complex conflicts.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread* linux-next: manual merge of the drm tree with the drm-fixes tree
@ 2018-12-07 2:31 Stephen Rothwell
0 siblings, 0 replies; 41+ messages in thread
From: Stephen Rothwell @ 2018-12-07 2:31 UTC (permalink / raw)
To: Dave Airlie, DRI
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
David Francis, Alex Deucher, Nicholas Kazlauskas
[-- Attachment #1: Type: text/plain, Size: 1450 bytes --]
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
between commit:
49f1c44b581b ("rm/amd/display: Fix unintialized max_bpc state values")
from the drm-fixes tree and commits:
c1ee92f94ce3 ("drm/amd: Add abm level drm property")
bb47de736661 ("drm/amdgpu: Set FreeSync state using drm VRR properties")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5a6edf65c9ea,32e791d9b9a8..000000000000
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@@ -3063,8 -3234,7 +3235,8 @@@ amdgpu_dm_connector_atomic_duplicate_st
__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
new_state->freesync_capable = state->freesync_capable;
- new_state->freesync_enable = state->freesync_enable;
+ new_state->max_bpc = state->max_bpc;
+ new_state->abm_level = state->abm_level;
return &new_state->base;
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2026-07-17 15:12 UTC | newest]
Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-06 13:47 linux-next: manual merge of the drm tree with the drm-fixes tree Mark Brown
-- strict thread matches above, loose matches on Subject: below --
2026-07-17 14:41 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 15:12 ` Mark Brown
2026-07-10 12:11 Mark Brown
2026-05-29 22:00 Mark Brown
2026-04-03 13:33 Mark Brown
2026-03-27 20:52 Mark Brown
2026-03-27 20:46 Mark Brown
2026-03-09 14:35 Mark Brown
2026-03-06 13:47 Mark Brown
2026-01-30 15:37 Mark Brown
2026-01-30 15:28 Mark Brown
2026-01-23 17:45 Mark Brown
2025-06-27 2:58 Stephen Rothwell
2024-10-18 1:56 Stephen Rothwell
2024-06-27 15:08 Mark Brown
2024-06-27 15:00 Mark Brown
2024-06-21 13:21 Mark Brown
2023-08-18 1:53 Stephen Rothwell
2023-02-13 0:23 Stephen Rothwell
2022-09-26 17:49 broonie
2022-02-25 16:37 broonie
2022-02-24 16:33 broonie
2021-08-06 12:04 Mark Brown
2021-08-10 11:56 ` Geert Uytterhoeven
2021-08-10 12:53 ` Stephen Rothwell
2020-07-10 2:28 Stephen Rothwell
2019-08-23 3:20 Stephen Rothwell
2019-07-05 2:50 Stephen Rothwell
2019-03-01 2:23 Stephen Rothwell
2019-03-01 23:29 ` Alex Deucher
2019-03-04 0:54 ` Stephen Rothwell
2019-03-11 12:36 ` Daniel Vetter
2018-12-14 1:51 Stephen Rothwell
2018-12-07 2:38 Stephen Rothwell
2018-12-07 2:31 Stephen Rothwell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox