diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm')
7 files changed, 319 insertions, 118 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 9ca517b65854..4823f8a32159 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 <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> @@ -618,6 +620,58 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) amdgpu_dm_crtc_handle_crc_window_irq(&acrtc->base); } #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); +} #endif static int dm_set_clockgating_state(void *handle, @@ -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, @@ -2708,8 +2751,7 @@ static void handle_hpd_rx_irq(void *param) * conflict, after implement i2c helper, this mutex should be * retired. */ - if (dc_link->type != dc_connection_mst_branch) - mutex_lock(&aconnector->hpd_lock); + mutex_lock(&aconnector->hpd_lock); read_hpd_rx_irq_data(dc_link, &hpd_irq_data); @@ -2726,13 +2768,15 @@ static void handle_hpd_rx_irq(void *param) } } - mutex_lock(&adev->dm.dc_lock); + if (!amdgpu_in_reset(adev)) { + mutex_lock(&adev->dm.dc_lock); #ifdef CONFIG_DRM_AMD_DC_HDCP result = dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data, NULL); #else result = dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL); #endif - mutex_unlock(&adev->dm.dc_lock); + mutex_unlock(&adev->dm.dc_lock); + } out: if (result && !is_mst_root_connector) { @@ -2776,10 +2820,10 @@ out: } #endif - if (dc_link->type != dc_connection_mst_branch) { + if (dc_link->type != dc_connection_mst_branch) drm_dp_cec_irq(&aconnector->dm_dp_aux.aux); - mutex_unlock(&aconnector->hpd_lock); - } + + mutex_unlock(&aconnector->hpd_lock); } static void register_hpd_handlers(struct amdgpu_device *adev) @@ -3151,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 @@ -3414,22 +3471,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; } @@ -3443,7 +3515,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; @@ -3452,7 +3524,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; @@ -3549,10 +3621,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 } @@ -3643,6 +3718,22 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail; } +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* Use Outbox interrupt */ + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + 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); + } +#endif + /* loops over all connectors on the board */ for (i = 0; i < link_cnt; i++) { struct dc_link *link = NULL; @@ -6560,13 +6651,13 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, { struct dc_stream_state *stream = NULL; struct drm_connector *connector; - struct drm_connector_state *new_con_state, *old_con_state; + struct drm_connector_state *new_con_state; struct amdgpu_dm_connector *aconnector; struct dm_connector_state *dm_conn_state; int i, j, clock, bpp; int vcpi, pbn_div, pbn = 0; - for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { + for_each_new_connector_in_state(state, connector, new_con_state, i) { aconnector = to_amdgpu_dm_connector(connector); @@ -8164,15 +8255,14 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state, static void amdgpu_dm_commit_cursors(struct drm_atomic_state *state) { struct drm_plane *plane; - struct drm_plane_state *old_plane_state, *new_plane_state; + struct drm_plane_state *old_plane_state; int i; /* * TODO: Make this per-stream so we don't issue redundant updates for * commits with multiple streams. */ - for_each_oldnew_plane_in_state(state, plane, old_plane_state, - new_plane_state, i) + for_each_old_plane_in_state(state, plane, old_plane_state, i) if (plane->type == DRM_PLANE_TYPE_CURSOR) handle_cursor_update(plane, old_plane_state); } @@ -10668,3 +10758,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 b2f2ccfc20bb..c6f79c7dfac4 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" @@ -54,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; @@ -62,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; @@ -135,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; @@ -164,6 +172,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 { @@ -178,6 +187,8 @@ struct amdgpu_display_manager { */ struct dmub_srv *dmub_srv; + struct dmub_notification *dmub_notify; + /** * @dmub_fb_info: * @@ -349,11 +360,17 @@ 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; - 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; @@ -418,6 +435,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 { @@ -600,4 +618,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_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 1b6b15708b96..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 @@ -925,6 +925,22 @@ static int hdcp_sink_capability_show(struct seq_file *m, void *data) return 0; } #endif + +/* + * Returns whether the connected display is internal and not hotpluggable. + * Example usage: cat /sys/kernel/debug/dri/0/DP-1/internal_display + */ +static int internal_display_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + struct dc_link *link = aconnector->dc_link; + + seq_printf(m, "Internal: %u\n", link->is_internal_display); + + return 0; +} + /* function description * * generic SDP message access for testing @@ -2361,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); @@ -2369,6 +2423,7 @@ DEFINE_SHOW_ATTRIBUTE(dp_lttpr_status); #ifdef CONFIG_DRM_AMD_DC_HDCP DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability); #endif +DEFINE_SHOW_ATTRIBUTE(internal_display); static const struct file_operations dp_dsc_clock_en_debugfs_fops = { .owner = THIS_MODULE, @@ -2594,13 +2649,17 @@ 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; } connector_debugfs_entries[] = { {"force_yuv420_output", &force_yuv420_output_fops}, {"output_bpc", &output_bpc_fops}, - {"trigger_hotplug", &trigger_hotplug_debugfs_fops} + {"trigger_hotplug", &trigger_hotplug_debugfs_fops}, + {"internal_display", &internal_display_fops} }; void connector_debugfs_init(struct amdgpu_dm_connector *connector) @@ -2616,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, @@ -2920,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; @@ -3134,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"); @@ -3215,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, 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..4646b0d02939 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 @@ -544,8 +544,10 @@ bool dm_helpers_dp_write_dsc_enable( ret = drm_dp_dpcd_write(aconnector->dsc_aux, DP_DSC_ENABLE, &enable_dsc, 1); } - if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT) - return dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT) { + ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); + DC_LOG_DC("Send DSC %s to sst display\n", enable_dsc ? "enable" : "disable"); + } return (ret > 0); } @@ -640,7 +642,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 +707,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/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 4a0c24ce5f7d..e6b2eec9fb59 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -278,6 +278,9 @@ dm_dp_mst_detect(struct drm_connector *connector, struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_dm_connector *master = aconnector->mst_port; + if (drm_connector_is_unregistered(connector)) + return connector_status_disconnected; + return drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr, aconnector->port); } |