From a273f315b949ac55694fedac9ee4ceeb47f537b0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 23 Apr 2021 16:46:19 -0400 Subject: drm/amdgpu/display: add documentation for dmcub_trace_event_en Was missing when this structure was updated. Fixes: 46a83eba276cd3 ("drm/amd/display: Add debugfs to control DMUB trace buffer events") Reviewed-by: Leo (Hanghong) Ma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index b2f2ccfc20bb..47c658ca3535 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -164,6 +164,7 @@ struct dal_allocation { * @compressor: Frame buffer compression buffer. See &struct dm_compressor_info * @force_timing_sync: set via debugfs. When set, indicates that all connected * displays will be forced to synchronize. + * @dmcub_trace_event_en: enable dmcub trace events */ struct amdgpu_display_manager { -- cgit v1.2.3-70-g09d2 From 118b4627d6777d8d422786ded6a0bd8e2934d11f Mon Sep 17 00:00:00 2001 From: Mikita Lipski Date: Wed, 14 Apr 2021 14:51:02 -0400 Subject: drm/amd/display: multi-eDP backlight support [why] Currently the assumption is that we are using a single eDP connector so there will only be one backlight object. Need changes to allow brightness update and reading for multiple eDP connectors. [how] - register a single device - turn backlight link from a pointer to an array of pointers - update brightness of all eDP links at the same time when request is registered - read brightness level only of the primary eDP panel - turn current_backlight_pwm and targer_backlight_pwm debugfs enteries into per connector enteries. Signed-off-by: Mikita Lipski Reviewed-by: Nicholas Kazlauskas Acked-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 ++++++++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 6 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 86 ++++++++++++---------- 3 files changed, 82 insertions(+), 52 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h') 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 15070bff27fa..e5efae695559 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3415,22 +3415,37 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) { struct amdgpu_display_manager *dm = bl_get_data(bd); struct amdgpu_dm_backlight_caps caps; - struct dc_link *link = NULL; + struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP]; u32 brightness; bool rc; + int i; amdgpu_dm_update_backlight_caps(dm); caps = dm->backlight_caps; - link = (struct dc_link *)dm->backlight_link; + for (i = 0; i < dm->num_of_edps; i++) + link[i] = (struct dc_link *)dm->backlight_link[i]; brightness = convert_brightness_from_user(&caps, bd->props.brightness); // Change brightness based on AUX property - if (caps.aux_support) - rc = dc_link_set_backlight_level_nits(link, true, brightness, - AUX_BL_DEFAULT_TRANSITION_TIME_MS); - else - rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0); + if (caps.aux_support) { + for (i = 0; i < dm->num_of_edps; i++) { + rc = dc_link_set_backlight_level_nits(link[i], true, brightness, + AUX_BL_DEFAULT_TRANSITION_TIME_MS); + if (!rc) { + DRM_ERROR("DM: Failed to update backlight via AUX on eDP[%d]\n", i); + break; + } + } + } else { + for (i = 0; i < dm->num_of_edps; i++) { + rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness, 0); + if (!rc) { + DRM_ERROR("DM: Failed to update backlight on eDP[%d]\n", i); + break; + } + } + } return rc ? 0 : 1; } @@ -3444,7 +3459,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) caps = dm->backlight_caps; if (caps.aux_support) { - struct dc_link *link = (struct dc_link *)dm->backlight_link; + struct dc_link *link = (struct dc_link *)dm->backlight_link[0]; u32 avg, peak; bool rc; @@ -3453,7 +3468,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) return bd->props.brightness; return convert_brightness_to_user(&caps, avg); } else { - int ret = dc_link_get_backlight_level(dm->backlight_link); + int ret = dc_link_get_backlight_level(dm->backlight_link[0]); if (ret == DC_ERROR_UNEXPECTED) return bd->props.brightness; @@ -3550,10 +3565,13 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, * DM initialization because not having a backlight control * is better then a black screen. */ - amdgpu_dm_register_backlight_device(dm); + if (!dm->backlight_dev) + amdgpu_dm_register_backlight_device(dm); - if (dm->backlight_dev) - dm->backlight_link = link; + if (dm->backlight_dev) { + dm->backlight_link[dm->num_of_edps] = link; + dm->num_of_edps++; + } } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 47c658ca3535..724ace502d25 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -46,6 +46,7 @@ #define AMDGPU_DM_MAX_CRTC 6 +#define AMDGPU_DM_MAX_NUM_EDP 2 /* #include "include/amdgpu_dal_power_if.h" #include "amdgpu_dm_irq.h" @@ -354,7 +355,10 @@ struct amdgpu_display_manager { struct backlight_device *backlight_dev; - const struct dc_link *backlight_link; + const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP]; + + uint8_t num_of_edps; + struct amdgpu_dm_backlight_caps backlight_caps; struct mod_freesync *freesync_module; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 8bf0b566612b..9fbbd0159119 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2377,6 +2377,44 @@ unlock: return size; } +/* + * Backlight at this moment. Read only. + * As written to display, taking ABM and backlight lut into account. + * Ranges from 0x0 to 0x10000 (= 100% PWM) + * + * Example usage: cat /sys/kernel/debug/dri/0/eDP-1/current_backlight + */ +static int current_backlight_show(struct seq_file *m, void *unused) +{ + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(m->private); + struct dc_link *link = aconnector->dc_link; + unsigned int backlight; + + backlight = dc_link_get_backlight_level(link); + seq_printf(m, "0x%x\n", backlight); + + return 0; +} + +/* + * Backlight value that is being approached. Read only. + * As written to display, taking ABM and backlight lut into account. + * Ranges from 0x0 to 0x10000 (= 100% PWM) + * + * Example usage: cat /sys/kernel/debug/dri/0/eDP-1/target_backlight + */ +static int target_backlight_show(struct seq_file *m, void *unused) +{ + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(m->private); + struct dc_link *link = aconnector->dc_link; + unsigned int backlight; + + backlight = dc_link_get_target_backlight_pwm(link); + seq_printf(m, "0x%x\n", backlight); + + return 0; +} + DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support); DEFINE_SHOW_ATTRIBUTE(dmub_fw_state); DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer); @@ -2611,6 +2649,9 @@ DEFINE_DEBUGFS_ATTRIBUTE(dmcub_trace_event_state_fops, dmcub_trace_event_state_g DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n"); +DEFINE_SHOW_ATTRIBUTE(current_backlight); +DEFINE_SHOW_ATTRIBUTE(target_backlight); + static const struct { char *name; const struct file_operations *fops; @@ -2634,8 +2675,13 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) dp_debugfs_entries[i].fops); } } - if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) + if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) { debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops); + debugfs_create_file("amdgpu_current_backlight_pwm", 0444, dir, connector, + ¤t_backlight_fops); + debugfs_create_file("amdgpu_target_backlight_pwm", 0444, dir, connector, + &target_backlight_fops); + } for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) { debugfs_create_file(connector_debugfs_entries[i].name, @@ -2938,38 +2984,6 @@ static ssize_t dtn_log_write( return size; } -/* - * Backlight at this moment. Read only. - * As written to display, taking ABM and backlight lut into account. - * Ranges from 0x0 to 0x10000 (= 100% PWM) - */ -static int current_backlight_show(struct seq_file *m, void *unused) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)m->private; - struct amdgpu_display_manager *dm = &adev->dm; - - unsigned int backlight = dc_link_get_backlight_level(dm->backlight_link); - - seq_printf(m, "0x%x\n", backlight); - return 0; -} - -/* - * Backlight value that is being approached. Read only. - * As written to display, taking ABM and backlight lut into account. - * Ranges from 0x0 to 0x10000 (= 100% PWM) - */ -static int target_backlight_show(struct seq_file *m, void *unused) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)m->private; - struct amdgpu_display_manager *dm = &adev->dm; - - unsigned int backlight = dc_link_get_target_backlight_pwm(dm->backlight_link); - - seq_printf(m, "0x%x\n", backlight); - return 0; -} - static int mst_topo_show(struct seq_file *m, void *unused) { struct amdgpu_device *adev = (struct amdgpu_device *)m->private; @@ -3152,8 +3166,6 @@ static int visual_confirm_get(void *data, u64 *val) return 0; } -DEFINE_SHOW_ATTRIBUTE(current_backlight); -DEFINE_SHOW_ATTRIBUTE(target_backlight); DEFINE_SHOW_ATTRIBUTE(mst_topo); DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get, visual_confirm_set, "%llu\n"); @@ -3233,10 +3245,6 @@ void dtn_debugfs_init(struct amdgpu_device *adev) struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *root = minor->debugfs_root; - debugfs_create_file("amdgpu_current_backlight_pwm", 0444, - root, adev, ¤t_backlight_fops); - debugfs_create_file("amdgpu_target_backlight_pwm", 0444, - root, adev, &target_backlight_fops); debugfs_create_file("amdgpu_mst_topology", 0444, root, adev, &mst_topo_fops); debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev, -- cgit v1.2.3-70-g09d2 From 81927e2808be5adace93c2012d45d6938d3a7aa0 Mon Sep 17 00:00:00 2001 From: Jude Shih Date: Tue, 20 Apr 2021 10:19:37 +0800 Subject: drm/amd/display: Support for DMUB AUX [WHY] To process AUX transactions with DMUB using inbox1 and outbox1 mail boxes. [How] 1) Added inbox1 command DMUB_CMD__DP_AUX_ACCESS to issue AUX commands to DMUB in dc_process_dmub_aux_transfer_async(). DMUB processes AUX cmd with DCN and sends reply back in an outbox1 message triggering an outbox1 interrupt to driver. 2) In existing driver implementation, AUX commands are processed synchronously by configuring DCN reg. But in DMUB AUX, driver sends an inbox1 message and waits for a conditional variable (CV) which will be signaled by outbox1 ISR. 3) DM will retrieve Outbox1 message and send back reply to upper layer and complete the AUX command Signed-off-by: Jude Shih Reviewed-by: Hanghong Ma Reviewed-by: Nicholas Kazlauskas Acked-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 193 ++++++++++++++++----- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 11 ++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 27 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 1 + drivers/gpu/drm/amd/display/dc/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 5 +- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 19 ++ drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 3 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 9 +- .../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 18 +- drivers/gpu/drm/amd/display/dc/irq_types.h | 2 +- 13 files changed, 240 insertions(+), 65 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h') 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 e5efae695559..bdbc577be65c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -35,6 +35,7 @@ #include "dc/inc/hw/abm.h" #include "dc/dc_dmub_srv.h" #include "dc/dc_edid_parser.h" +#include "dc/dc_stat.h" #include "amdgpu_dm_trace.h" #include "vid.h" @@ -59,6 +60,7 @@ #include "ivsrcid/ivsrcid_vislands30.h" +#include "i2caux_interface.h" #include #include #include @@ -620,6 +622,58 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) #endif #endif +/** + * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt + * @interrupt_params: used for determining the Outbox instance + * + * 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; + 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 }; + uint32_t count = 0; + + if (dc_enable_dmub_notifications(adev->dm.dc)) { + if (irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) { + do { + dc_stat_get_dmub_notification(adev->dm.dc, ¬ify); + } while (notify.pending_notification); + + if (adev->dm.dmub_notify) + memcpy(adev->dm.dmub_notify, ¬ify, sizeof(struct dmub_notification)); + if (notify.type == DMUB_NOTIFICATION_AUX_REPLY) + complete(&adev->dm.dmub_aux_transfer_done); + // TODO : HPD Implementation + + } else { + DRM_ERROR("DM: Failed to receive correct outbox IRQ !"); + } + } + + + 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_DEBUG_DRIVER("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); + + ASSERT(count <= DMUB_TRACE_MAX_READ); +} + static int dm_set_clockgating_state(void *handle, enum amd_clockgating_state state) { @@ -938,32 +992,6 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) } #if defined(CONFIG_DRM_AMD_DC_DCN) -#define DMUB_TRACE_MAX_READ 64 -static void dm_dmub_trace_high_irq(void *interrupt_params) -{ - 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 }; - uint32_t count = 0; - - 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_DEBUG_DRIVER("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); - - ASSERT(count <= DMUB_TRACE_MAX_READ); -} - static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config) { uint64_t pt_base; @@ -1220,6 +1248,16 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) adev->dm.crc_rd_wrk = amdgpu_dm_crtc_secure_display_create_work(); #endif + if (dc_enable_dmub_notifications(adev->dm.dc)) { + init_completion(&adev->dm.dmub_aux_transfer_done); + adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL); + if (!adev->dm.dmub_notify) { + DRM_INFO("amdgpu: fail to allocate adev->dm.dmub_notify"); + goto error; + } + amdgpu_dm_outbox_init(adev); + } + if (amdgpu_dm_initialize_drm_device(adev)) { DRM_ERROR( "amdgpu: failed to initialize sw for display support.\n"); @@ -1293,6 +1331,11 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.dc->ctx->dmub_srv = NULL; } + if (dc_enable_dmub_notifications(adev->dm.dc)) { + kfree(adev->dm.dmub_notify); + adev->dm.dmub_notify = NULL; + } + if (adev->dm.dmub_bo) amdgpu_bo_free_kernel(&adev->dm.dmub_bo, &adev->dm.dmub_bo_gpu_addr, @@ -3152,38 +3195,51 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev) } - if (dc->ctx->dmub_srv) { - i = DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT; - r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->dmub_trace_irq); + /* HPD */ + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT, + &adev->hpd_irq); + if (r) { + DRM_ERROR("Failed to add hpd irq id!\n"); + return r; + } - if (r) { - DRM_ERROR("Failed to add dmub trace irq id!\n"); - return r; - } + register_hpd_handlers(adev); - int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + return 0; +} +/* 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_ERROR("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); + dc_interrupt_to_irq_source(dc, i, 0); - c_irq_params = &adev->dm.dmub_trace_params[0]; + c_irq_params = &adev->dm.dmub_outbox_params[0]; c_irq_params->adev = adev; c_irq_params->irq_src = int_params.irq_source; amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_dmub_trace_high_irq, c_irq_params); - } - - /* HPD */ - r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT, - &adev->hpd_irq); - if (r) { - DRM_ERROR("Failed to add hpd irq id!\n"); - return r; + dm_dmub_outbox1_low_irq, c_irq_params); } - register_hpd_handlers(adev); - return 0; } #endif @@ -3662,6 +3718,22 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail; } + /* Use Outbox interrupt */ + switch (adev->asic_type) { +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: +#endif + case CHIP_RENOIR: + if (register_outbox_irq_handlers(dm->adev)) { + DRM_ERROR("DM: Failed to initialize IRQ\n"); + goto fail; + } + break; + default: + DRM_DEBUG_KMS("Unsupported ASIC type for outbox: 0x%X\n", adev->asic_type); + } + /* loops over all connectors on the board */ for (i = 0; i < link_cnt; i++) { struct dc_link *link = NULL; @@ -10707,3 +10779,30 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address, return value; } + +int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned int linkIndex, + struct aux_payload *payload, enum aux_return_code_type *operation_result) +{ + struct amdgpu_device *adev = ctx->driver_context; + int ret = 0; + + dc_process_dmub_aux_transfer_async(ctx->dc, linkIndex, payload); + ret = wait_for_completion_interruptible_timeout(&adev->dm.dmub_aux_transfer_done, 10*HZ); + if (ret == 0) { + *operation_result = AUX_RET_ERROR_TIMEOUT; + return -1; + } + *operation_result = (enum aux_return_code_type)adev->dm.dmub_notify->result; + + if (adev->dm.dmub_notify->result == AUX_RET_SUCCESS) { + (*payload->reply) = adev->dm.dmub_notify->aux_reply.command; + + // For read case, Copy data to payload + if (!payload->write && adev->dm.dmub_notify->aux_reply.length && + (*payload->reply == AUX_TRANSACTION_REPLY_AUX_ACK)) + memcpy(payload->data, adev->dm.dmub_notify->aux_reply.data, + adev->dm.dmub_notify->aux_reply.length); + } + + return adev->dm.dmub_notify->aux_reply.length; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 724ace502d25..4712984efb9a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -55,6 +55,8 @@ #include "irq_types.h" #include "signal_types.h" #include "amdgpu_dm_crc.h" +struct aux_payload; +enum aux_return_code_type; /* Forward declarations */ struct amdgpu_device; @@ -63,6 +65,7 @@ struct dc; struct amdgpu_bo; struct dmub_srv; struct dc_plane_state; +struct dmub_notification; struct common_irq_params { struct amdgpu_device *adev; @@ -180,6 +183,8 @@ struct amdgpu_display_manager { */ struct dmub_srv *dmub_srv; + struct dmub_notification *dmub_notify; + /** * @dmub_fb_info: * @@ -351,6 +356,9 @@ struct amdgpu_display_manager { struct common_irq_params dmub_trace_params[1]; + struct common_irq_params + dmub_outbox_params[1]; + spinlock_t irq_handler_list_table_lock; struct backlight_device *backlight_dev; @@ -423,6 +431,7 @@ struct amdgpu_display_manager { * DAL fb memory allocation list, for communication with SMU. */ struct list_head da_list; + struct completion dmub_aux_transfer_done; }; enum dsc_clock_force_state { @@ -605,4 +614,6 @@ void amdgpu_dm_update_connector_after_detect( extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; +int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned int linkIndex, + struct aux_payload *payload, enum aux_return_code_type *operation_result); #endif /* __AMDGPU_DM_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index e8b325a828c1..90eacdac0ea0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -640,7 +640,14 @@ enum dc_edid_status dm_helpers_read_local_edid( return edid_status; } - +int dm_helper_dmub_aux_transfer_sync( + struct dc_context *ctx, + const struct dc_link *link, + struct aux_payload *payload, + enum aux_return_code_type *operation_result) +{ + return amdgpu_dm_process_dmub_aux_transfer_sync(ctx, link->link_index, payload, operation_result); +} void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks) { /* TODO: something */ @@ -698,12 +705,12 @@ void dm_helpers_free_gpu_mem( } } -bool dm_helpers_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable) +bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable) { enum dc_irq_source irq_source; bool ret; - irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX0; + irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX; ret = dc_interrupt_set(ctx->dc, irq_source, enable); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index b3ed7e777720..40f617bbb86f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -769,6 +769,18 @@ static int amdgpu_dm_set_vline0_irq_state(struct amdgpu_device *adev, __func__); } +static int amdgpu_dm_set_dmub_outbox_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned int crtc_id, + enum amdgpu_interrupt_state state) +{ + enum dc_irq_source irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX; + bool st = (state == AMDGPU_IRQ_STATE_ENABLE); + + dc_interrupt_set(adev->dm.dc, irq_source, st); + return 0; +} + static int amdgpu_dm_set_vupdate_irq_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned int crtc_id, @@ -805,6 +817,11 @@ static const struct amdgpu_irq_src_funcs dm_vline0_irq_funcs = { .process = amdgpu_dm_irq_handler, }; +static const struct amdgpu_irq_src_funcs dm_dmub_outbox_irq_funcs = { + .set = amdgpu_dm_set_dmub_outbox_irq_state, + .process = amdgpu_dm_irq_handler, +}; + static const struct amdgpu_irq_src_funcs dm_vupdate_irq_funcs = { .set = amdgpu_dm_set_vupdate_irq_state, .process = amdgpu_dm_irq_handler, @@ -827,13 +844,15 @@ static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = { void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) { - adev->crtc_irq.num_types = adev->mode_info.num_crtc; adev->crtc_irq.funcs = &dm_crtc_irq_funcs; adev->vline0_irq.num_types = adev->mode_info.num_crtc; adev->vline0_irq.funcs = &dm_vline0_irq_funcs; + adev->dmub_outbox_irq.num_types = 1; + adev->dmub_outbox_irq.funcs = &dm_dmub_outbox_irq_funcs; + adev->vupdate_irq.num_types = adev->mode_info.num_crtc; adev->vupdate_irq.funcs = &dm_vupdate_irq_funcs; @@ -846,6 +865,12 @@ void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) adev->hpd_irq.num_types = adev->mode_info.num_hpd; adev->hpd_irq.funcs = &dm_hpd_irq_funcs; } +void amdgpu_dm_outbox_init(struct amdgpu_device *adev) +{ + dc_interrupt_set(adev->dm.dc, + DC_IRQ_SOURCE_DMCUB_OUTBOX, + true); +} /** * amdgpu_dm_hpd_init - hpd setup callback. diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 82f8e761beca..2349238a626b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -82,6 +82,7 @@ void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev); +void amdgpu_dm_outbox_init(struct amdgpu_device *adev); void amdgpu_dm_hpd_init(struct amdgpu_device *adev); void amdgpu_dm_hpd_fini(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index f33847299bca..5cd89f7e7772 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -54,7 +54,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) -DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ +DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \ dc_link_enc_cfg.o diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 64414c51312d..3bdd54e6248a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -658,7 +658,10 @@ int dc_link_aux_transfer_raw(struct ddc_service *ddc, struct aux_payload *payload, enum aux_return_code_type *operation_result) { - return dce_aux_transfer_raw(ddc, payload, operation_result); + if (dc_enable_dmub_notifications(ddc->ctx->dc)) + return dce_aux_transfer_dmub_raw(ddc, payload, operation_result); + else + return dce_aux_transfer_raw(ddc, payload, operation_result); } /* dc_link_aux_transfer_with_retries() - Attempt to submit an diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 6b72af2b3f4c..c5dc3a947020 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -180,5 +180,5 @@ bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_bu void dc_dmub_trace_event_control(struct dc *dc, bool enable) { - dm_helpers_dmub_outbox0_interrupt_control(dc->ctx, enable); + dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 87d57e81de12..83d97dfe328f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -595,6 +595,25 @@ int dce_aux_transfer_raw(struct ddc_service *ddc, return res; } +int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, + struct aux_payload *payload, + enum aux_return_code_type *operation_result) +{ + struct ddc *ddc_pin = ddc->ddc_pin; + + if (ddc_pin != NULL) { + struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; + /* XXX: Workaround to configure ddc channels for aux transactions */ + if (!acquire(aux_engine, ddc_pin)) { + *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; + return -1; + } + release_engine(aux_engine); + } + + return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result); +} + #define AUX_MAX_RETRIES 7 #define AUX_MAX_DEFER_RETRIES 7 #define AUX_MAX_I2C_DEFER_RETRIES 7 diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h index 566b1bddd8cc..e69f1899fbf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h @@ -304,6 +304,9 @@ int dce_aux_transfer_raw(struct ddc_service *ddc, struct aux_payload *cmd, enum aux_return_code_type *operation_result); +int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, + struct aux_payload *payload, + enum aux_return_code_type *operation_result); bool dce_aux_transfer_with_retries(struct ddc_service *ddc, struct aux_payload *cmd); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 7617fab9e1f9..304d50d16d01 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -34,6 +34,8 @@ #include "dc.h" struct dp_mst_stream_allocation_table; +struct aux_payload; +enum aux_return_code_type; /* * Allocate memory accessible by the GPU @@ -158,6 +160,11 @@ void dm_set_dcn_clocks( struct dc_context *ctx, struct dc_clocks *clks); -bool dm_helpers_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable); +bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable); +int dm_helper_dmub_aux_transfer_sync( + struct dc_context *ctx, + const struct dc_link *link, + struct aux_payload *payload, + enum aux_return_code_type *operation_result); #endif /* __DM_HELPERS__ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c index 1a5be2792055..ed54e1c819be 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -58,8 +58,8 @@ enum dc_irq_source to_dal_irq_source_dcn21( return DC_IRQ_SOURCE_VBLANK5; case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK6; - case DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT: - return DC_IRQ_SOURCE_DMCUB_OUTBOX0; + case DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT: + return DC_IRQ_SOURCE_DMCUB_OUTBOX; case DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL: return DC_IRQ_SOURCE_DC1_VLINE0; case DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL: @@ -187,7 +187,7 @@ static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { .ack = NULL }; -static const struct irq_source_info_funcs dmub_trace_irq_info_funcs = { +static const struct irq_source_info_funcs dmub_outbox_irq_info_funcs = { .set = NULL, .ack = NULL }; @@ -301,11 +301,11 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .funcs = &vline0_irq_info_funcs\ } -#define dmub_trace_int_entry()\ - [DC_IRQ_SOURCE_DMCUB_OUTBOX0] = {\ - IRQ_REG_ENTRY_DMUB(DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX0_READY_INT_EN,\ - DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX0_READY_INT_ACK),\ - .funcs = &dmub_trace_irq_info_funcs\ +#define dmub_outbox_int_entry()\ + [DC_IRQ_SOURCE_DMCUB_OUTBOX] = {\ + IRQ_REG_ENTRY_DMUB(DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX1_READY_INT_EN,\ + DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX1_READY_INT_ACK),\ + .funcs = &dmub_outbox_irq_info_funcs\ } #define dummy_irq_entry() \ @@ -426,7 +426,7 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NUMBER] = { vline0_int_entry(3), vline0_int_entry(4), vline0_int_entry(5), - dmub_trace_int_entry(), + dmub_outbox_int_entry(), }; static const struct irq_service_funcs irq_service_funcs_dcn21 = { diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index ae8f47ec0f8c..5f9346622301 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -150,7 +150,7 @@ enum dc_irq_source { DC_IRQ_SOURCE_DC4_VLINE1, DC_IRQ_SOURCE_DC5_VLINE1, DC_IRQ_SOURCE_DC6_VLINE1, - DC_IRQ_DMCUB_OUTBOX1, + DC_IRQ_SOURCE_DMCUB_OUTBOX, DC_IRQ_SOURCE_DMCUB_OUTBOX0, DAL_IRQ_SOURCES_NUMBER -- cgit v1.2.3-70-g09d2 From cbd4945ca5b88ed015ab61e70f788de1a71bf9cc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 23 Apr 2021 16:43:18 -0400 Subject: drm/amdgpu/display: fix dal_allocation documentation Add missing structure elements. Fixes: 0dd79532340568 ("drm/amdgpu/display: Implement functions to let DC allocate GPU memory") Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 4712984efb9a..c6f79c7dfac4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -139,6 +139,10 @@ struct amdgpu_dm_backlight_caps { /** * struct dal_allocation - Tracks mapped FB memory for SMU communication + * @list: list of dal allocations + * @bo: GPU buffer object + * @cpu_ptr: CPU virtual address of the GPU buffer object + * @gpu_addr: GPU virtual address of the GPU buffer object */ struct dal_allocation { struct list_head list; -- cgit v1.2.3-70-g09d2