diff options
author | Dave Airlie <airlied@redhat.com> | 2021-07-30 16:48:35 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2021-07-30 16:48:35 +1000 |
commit | 04d505de7f82c8f2daa6139b460b05dc01e354e0 (patch) | |
tree | a5b4f62c721cffa1ff4f1625d76e9d8f79a9d0df /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
parent | f1b7996551a40a4ebb551130c83077a0cabcb935 (diff) | |
parent | 544dcd74b7093ad4befac99b11d90331aa73348e (diff) |
Merge tag 'amd-drm-next-5.15-2021-07-29' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.15-2021-07-29:
amdgpu:
- VCN/JPEG power down sequencing fixes
- Various navi pcie link handling fixes
- Clockgating fixes
- Yellow Carp fixes
- Beige Goby fixes
- Misc code cleanups
- S0ix fixes
- SMU i2c bus rework
- EEPROM handling rework
- PSP ucode handling cleanup
- SMU error handling rework
- AMD HDMI freesync fixes
- USB PD firmware update rework
- MMIO based vram access rework
- Misc display fixes
- Backlight fixes
- Add initial Cyan Skillfish support
- Overclocking fixes suspend/resume
amdkfd:
- Sysfs leak fix
- Add counters for vm faults and migration
- GPUVM TLB optimizations
radeon:
- Misc fixes
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210730033455.3852-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 260 |
1 files changed, 179 insertions, 81 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d3a2a5ff57e9..986c9d29d686 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -618,6 +618,7 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) } #endif +#define DMUB_TRACE_MAX_READ 64 /** * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt * @interrupt_params: used for determining the Outbox instance @@ -625,7 +626,6 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) * Handles the Outbox Interrupt * event handler. */ -#define DMUB_TRACE_MAX_READ 64 static void dm_dmub_outbox1_low_irq(void *interrupt_params) { struct dmub_notification notify; @@ -2412,6 +2412,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) static const u8 pre_computed_values[] = { 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; + int i; if (!aconnector || !aconnector->dc_link) return; @@ -2423,15 +2424,21 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) conn_base = &aconnector->base; adev = drm_to_adev(conn_base->dev); dm = &adev->dm; - caps = &dm->backlight_caps; + for (i = 0; i < dm->num_of_edps; i++) { + if (link == dm->backlight_link[i]) + break; + } + if (i >= dm->num_of_edps) + return; + caps = &dm->backlight_caps[i]; caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; caps->aux_support = false; max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll; min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll; - if (caps->ext_caps->bits.oled == 1 || + 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->ext_caps->bits.hdr_aux_backlight_control == 1*/) caps->aux_support = true; if (amdgpu_backlight == 0) @@ -3423,35 +3430,36 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) -static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) +static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, + int bl_idx) { #if defined(CONFIG_ACPI) struct amdgpu_dm_backlight_caps caps; memset(&caps, 0, sizeof(caps)); - if (dm->backlight_caps.caps_valid) + if (dm->backlight_caps[bl_idx].caps_valid) return; amdgpu_acpi_get_backlight_caps(&caps); if (caps.caps_valid) { - dm->backlight_caps.caps_valid = true; + dm->backlight_caps[bl_idx].caps_valid = true; if (caps.aux_support) return; - dm->backlight_caps.min_input_signal = caps.min_input_signal; - dm->backlight_caps.max_input_signal = caps.max_input_signal; + dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal; + dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal; } else { - dm->backlight_caps.min_input_signal = + dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; - dm->backlight_caps.max_input_signal = + dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; } #else - if (dm->backlight_caps.aux_support) + if (dm->backlight_caps[bl_idx].aux_support) return; - dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; - dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; + dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; + dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; #endif } @@ -3502,41 +3510,31 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap } static int 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[AMDGPU_DM_MAX_NUM_EDP]; - u32 brightness[AMDGPU_DM_MAX_NUM_EDP]; + struct dc_link *link; + u32 brightness; bool rc; - int i; - amdgpu_dm_update_backlight_caps(dm); - caps = dm->backlight_caps; + amdgpu_dm_update_backlight_caps(dm, bl_idx); + caps = dm->backlight_caps[bl_idx]; - for (i = 0; i < dm->num_of_edps; i++) { - dm->brightness[i] = user_brightness; - brightness[i] = convert_brightness_from_user(&caps, dm->brightness[i]); - link[i] = (struct dc_link *)dm->backlight_link[i]; - } + dm->brightness[bl_idx] = user_brightness; + brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]); + link = (struct dc_link *)dm->backlight_link[bl_idx]; /* Change brightness based on AUX property */ if (caps.aux_support) { - for (i = 0; i < dm->num_of_edps; i++) { - rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i], - AUX_BL_DEFAULT_TRANSITION_TIME_MS); - if (!rc) { - DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i); - break; - } - } + rc = dc_link_set_backlight_level_nits(link, true, brightness, + AUX_BL_DEFAULT_TRANSITION_TIME_MS); + if (!rc) + DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx); } else { - for (i = 0; i < dm->num_of_edps; i++) { - rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0); - if (!rc) { - DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i); - break; - } - } + rc = dc_link_set_backlight_level(link, brightness, 0); + if (!rc) + DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx); } return rc ? 0 : 1; @@ -3545,33 +3543,41 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) { struct amdgpu_display_manager *dm = bl_get_data(bd); + int i; - amdgpu_dm_backlight_set_level(dm, bd->props.brightness); + 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) +static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm, + int bl_idx) { struct amdgpu_dm_backlight_caps caps; + struct dc_link *link = (struct dc_link *)dm->backlight_link[bl_idx]; - amdgpu_dm_update_backlight_caps(dm); - caps = dm->backlight_caps; + amdgpu_dm_update_backlight_caps(dm, bl_idx); + caps = dm->backlight_caps[bl_idx]; if (caps.aux_support) { - struct dc_link *link = (struct dc_link *)dm->backlight_link[0]; u32 avg, peak; bool rc; rc = dc_link_get_backlight_level_nits(link, &avg, &peak); if (!rc) - return dm->brightness[0]; + return dm->brightness[bl_idx]; return convert_brightness_to_user(&caps, avg); } else { - int ret = dc_link_get_backlight_level(dm->backlight_link[0]); + int ret = dc_link_get_backlight_level(link); if (ret == DC_ERROR_UNEXPECTED) - return dm->brightness[0]; + return dm->brightness[bl_idx]; return convert_brightness_to_user(&caps, ret); } } @@ -3579,8 +3585,15 @@ static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm) static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) { struct amdgpu_display_manager *dm = bl_get_data(bd); + int i; - return amdgpu_dm_backlight_get_level(dm); + 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 = { @@ -3594,31 +3607,28 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) { char bl_name[16]; struct backlight_properties props = { 0 }; - int i; - amdgpu_dm_update_backlight_caps(dm); - for (i = 0; i < dm->num_of_edps; i++) - dm->brightness[i] = AMDGPU_MAX_BL_LEVEL; + amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps); + dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL; props.max_brightness = AMDGPU_MAX_BL_LEVEL; props.brightness = AMDGPU_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", - adev_to_drm(dm->adev)->primary->index); + adev_to_drm(dm->adev)->primary->index + dm->num_of_edps); - dm->backlight_dev = backlight_device_register(bl_name, - adev_to_drm(dm->adev)->dev, - dm, - &amdgpu_dm_backlight_ops, - &props); + dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name, + adev_to_drm(dm->adev)->dev, + dm, + &amdgpu_dm_backlight_ops, + &props); - if (IS_ERR(dm->backlight_dev)) + if (IS_ERR(dm->backlight_dev[dm->num_of_edps])) DRM_ERROR("DM: Backlight registration failed!\n"); else DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); } - #endif static int initialize_plane(struct amdgpu_display_manager *dm, @@ -3675,10 +3685,10 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, * DM initialization because not having a backlight control * is better then a black screen. */ - if (!dm->backlight_dev) + if (!dm->backlight_dev[dm->num_of_edps]) amdgpu_dm_register_backlight_device(dm); - if (dm->backlight_dev) { + if (dm->backlight_dev[dm->num_of_edps]) { dm->backlight_link[dm->num_of_edps] = link; dm->num_of_edps++; } @@ -4747,7 +4757,7 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, const bool force_disable_dcc) { const uint64_t modifier = afb->base.modifier; - int ret; + int ret = 0; fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier); tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier); @@ -4765,9 +4775,9 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size); if (ret) - return ret; + drm_dbg_kms(adev_to_drm(adev), "validate_dcc: returned error: %d\n", ret); - return 0; + return ret; } static int @@ -6198,6 +6208,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) const struct dc_link *link = aconnector->dc_link; struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_display_manager *dm = &adev->dm; + int i; /* * Call only if mst_mgr was iniitalized before since it's not done @@ -6208,12 +6219,11 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - - if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && - link->type != dc_connection_none && - dm->backlight_dev) { - backlight_device_unregister(dm->backlight_dev); - dm->backlight_dev = NULL; + for (i = 0; i < dm->num_of_edps; i++) { + if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) { + backlight_device_unregister(dm->backlight_dev[i]); + dm->backlight_dev[i] = NULL; + } } #endif @@ -7570,8 +7580,10 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector) * 60 - Commonly used * 48,72,96 - Multiples of 24 */ - const uint32_t common_rates[] = { 23976, 24000, 25000, 29970, 30000, - 48000, 50000, 60000, 72000, 96000 }; + static const uint32_t common_rates[] = { + 23976, 24000, 25000, 29970, 30000, + 48000, 50000, 60000, 72000, 96000 + }; /* * Find mode with highest refresh rate with the same resolution @@ -9191,8 +9203,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) /* restore the backlight level */ - if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0])) - amdgpu_dm_backlight_set_level(dm, dm->brightness[0]); + for (i = 0; i < dm->num_of_edps; i++) { + if (dm->backlight_dev[i] && + (amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i])) + amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]); + } #endif /* * send vblank event on all events not handled in flip and @@ -10549,13 +10564,68 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc, return capable; } -static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, +static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm, + unsigned int offset, + unsigned int total_length, + uint8_t *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->total_length = total_length; + memcpy(input->payload, data, length); + + res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd); + if (!res) { + DRM_ERROR("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_ERROR("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; + } else { + DRM_WARN("Unknown EDID CEA parser results\n"); + return false; + } + + return true; +} + +static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm, uint8_t *edid_ext, int len, struct amdgpu_hdmi_vsdb_info *vsdb_info) { int i; - struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev); - struct dc *dc = adev->dm.dc; /* send extension block to DMCU for parsing */ for (i = 0; i < len; i += 8) { @@ -10563,14 +10633,14 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, int offset; /* send 8 bytes a time */ - if (!dc_edid_parser_send_cea(dc, i, len, &edid_ext[i], 8)) + 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(dc, &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; @@ -10584,7 +10654,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, } /* check for ack*/ - res = dc_edid_parser_recv_cea_ack(dc, &offset); + res = dc_edid_parser_recv_cea_ack(dm->dc, &offset); if (!res) return false; } @@ -10592,6 +10662,34 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, return false; } +static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm, + uint8_t *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, + uint8_t *edid_ext, int len, + struct amdgpu_hdmi_vsdb_info *vsdb_info) +{ + struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev); + + if (adev->dm.dmub_srv) + return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info); + else + return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info); +} + static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) { |