Loading msm/dp/dp_debug.c +35 −0 Original line number Diff line number Diff line Loading @@ -2277,6 +2277,37 @@ static int dp_debug_init_feature_toggle(struct dp_debug_private *debug, return rc; } static int dp_debug_init_configs(struct dp_debug_private *debug, struct dentry *dir) { int rc = 0; struct dentry *file; file = debugfs_create_ulong("connect_notification_delay_ms", 0644, dir, &debug->dp_debug.connect_notification_delay_ms); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs connect_notification_delay_ms failed, rc=%d\n", DEBUG_NAME, rc); return rc; } debug->dp_debug.connect_notification_delay_ms = DEFAULT_CONNECT_NOTIFICATION_DELAY_MS; file = debugfs_create_u32("disconnect_delay_ms", 0644, dir, &debug->dp_debug.disconnect_delay_ms); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs disconnect_delay_ms failed, rc=%d\n", DEBUG_NAME, rc); return rc; } debug->dp_debug.disconnect_delay_ms = DEFAULT_DISCONNECT_DELAY_MS; return rc; } static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; Loading Loading @@ -2343,6 +2374,10 @@ static int dp_debug_init(struct dp_debug *dp_debug) if (rc) goto error_remove_dir; rc = dp_debug_init_configs(debug, dir); if (rc) goto error_remove_dir; return 0; error_remove_dir: Loading msm/dp/dp_debug.h +12 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,11 @@ pr_err("[drm:%s][msm-dp-err][%-4d]"fmt, __func__, \ current->pid, ##__VA_ARGS__) #define DEFAULT_DISCONNECT_DELAY_MS 0 #define MAX_DISCONNECT_DELAY_MS 10000 #define DEFAULT_CONNECT_NOTIFICATION_DELAY_MS 150 #define MAX_CONNECT_NOTIFICATION_DELAY_MS 5000 /** * struct dp_debug * @debug_en: specifies whether debug mode enabled Loading @@ -63,6 +68,10 @@ * @mst_sim_remove_con: specifies whether sim connector is to be removed * @mst_sim_remove_con_id: specifies id of sim connector to be removed * @mst_port_cnt: number of mst ports to be added during hpd * @connect_notification_delay_ms: time (in ms) to wait for any attention * messages before sending the connect notification uevent * @disconnect_delay_ms: time (in ms) to wait before turning off the mainlink * in response to HPD low of cable disconnect event */ struct dp_debug { bool debug_en; Loading @@ -85,6 +94,9 @@ struct dp_debug { bool mst_sim_remove_con; int mst_sim_remove_con_id; u32 mst_port_cnt; unsigned long connect_notification_delay_ms; u32 disconnect_delay_ms; struct dp_mst_connector mst_connector_cache; u8 *(*get_edid)(struct dp_debug *dp_debug); void (*abort)(struct dp_debug *dp_debug); Loading msm/dp/dp_display.c +35 −3 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <linux/of_irq.h> #include <linux/soc/qcom/fsa4480-i2c.h> #include <linux/usb/phy.h> #include <linux/jiffies.h> #include "sde_connector.h" Loading Loading @@ -158,6 +159,7 @@ struct dp_display_private { struct device_node *aux_switch_node; struct dentry *root; struct completion notification_comp; struct completion attention_comp; struct dp_hpd *hpd; struct dp_parser *parser; Loading Loading @@ -1026,6 +1028,8 @@ static void dp_display_host_deinit(struct dp_display_private *dp) static int dp_display_process_hpd_high(struct dp_display_private *dp) { int rc = -EINVAL; unsigned long wait_timeout_ms; unsigned long t; SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state); mutex_lock(&dp->session_lock); Loading Loading @@ -1101,7 +1105,14 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) * Delay the HPD connect notification to see if sink generates any * IRQ HPDs immediately after the HPD high. */ usleep_range(10000, 10100); reinit_completion(&dp->attention_comp); wait_timeout_ms = min_t(unsigned long, dp->debug->connect_notification_delay_ms, (unsigned long) MAX_CONNECT_NOTIFICATION_DELAY_MS); t = wait_for_completion_timeout(&dp->attention_comp, msecs_to_jiffies(wait_timeout_ms)); DP_DEBUG("wait_timeout=%lu ms, time_waited=%u ms\n", wait_timeout_ms, jiffies_to_msecs(t)); /* * If an IRQ HPD is pending, then do not send a connect notification. Loading @@ -1118,7 +1129,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) */ if (!dp->mst.mst_active && (work_busy(&dp->attention_work) == WORK_BUSY_PENDING)) { SDE_EVT32_EXTERNAL(dp->state, 99); SDE_EVT32_EXTERNAL(dp->state, 99, jiffies_to_msecs(t)); DP_DEBUG("Attention pending, skip HPD notification\n"); goto skip_notify; } Loading @@ -1127,7 +1138,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp_display_send_hpd_notification(dp); skip_notify: SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state, rc); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state, wait_timeout_ms, rc); return rc; } Loading Loading @@ -1333,6 +1345,9 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp) static void dp_display_disconnect_sync(struct dp_display_private *dp) { int disconnect_delay_ms; SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state); /* cancel any pending request */ dp_display_state_add(DP_STATE_ABORTED); Loading @@ -1344,7 +1359,22 @@ static void dp_display_disconnect_sync(struct dp_display_private *dp) cancel_work_sync(&dp->attention_work); flush_workqueue(dp->wq); /* * Delay the teardown of the mainlink for better interop experience. * It is possible that certain sinks can issue an HPD high immediately * following an HPD low as soon as they detect the mainlink being * turned off. This can sometimes result in the HPD low pulse getting * lost with certain cable. This issue is commonly seen when running * DP LL CTS test 4.2.1.3. */ disconnect_delay_ms = min_t(u32, dp->debug->disconnect_delay_ms, (u32) MAX_DISCONNECT_DELAY_MS); DP_DEBUG("disconnect delay = %d ms\n", disconnect_delay_ms); msleep(disconnect_delay_ms); dp_display_handle_disconnect(dp); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state, disconnect_delay_ms); } static int dp_display_usbpd_disconnect_cb(struct device *dev) Loading Loading @@ -1572,6 +1602,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) } else if ((dp->hpd->hpd_irq && dp_display_state_is(DP_STATE_READY)) || dp->debug->mst_hpd_sim) { queue_work(dp->wq, &dp->attention_work); complete_all(&dp->attention_comp); } else if (dp->process_hpd_connect || !dp_display_state_is(DP_STATE_CONNECTED)) { dp_display_state_remove(DP_STATE_ABORTED); Loading Loading @@ -3384,6 +3415,7 @@ static int dp_display_probe(struct platform_device *pdev) } init_completion(&dp->notification_comp); init_completion(&dp->attention_comp); dp->pdev = pdev; dp->name = "drm_dp"; Loading Loading
msm/dp/dp_debug.c +35 −0 Original line number Diff line number Diff line Loading @@ -2277,6 +2277,37 @@ static int dp_debug_init_feature_toggle(struct dp_debug_private *debug, return rc; } static int dp_debug_init_configs(struct dp_debug_private *debug, struct dentry *dir) { int rc = 0; struct dentry *file; file = debugfs_create_ulong("connect_notification_delay_ms", 0644, dir, &debug->dp_debug.connect_notification_delay_ms); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs connect_notification_delay_ms failed, rc=%d\n", DEBUG_NAME, rc); return rc; } debug->dp_debug.connect_notification_delay_ms = DEFAULT_CONNECT_NOTIFICATION_DELAY_MS; file = debugfs_create_u32("disconnect_delay_ms", 0644, dir, &debug->dp_debug.disconnect_delay_ms); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs disconnect_delay_ms failed, rc=%d\n", DEBUG_NAME, rc); return rc; } debug->dp_debug.disconnect_delay_ms = DEFAULT_DISCONNECT_DELAY_MS; return rc; } static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; Loading Loading @@ -2343,6 +2374,10 @@ static int dp_debug_init(struct dp_debug *dp_debug) if (rc) goto error_remove_dir; rc = dp_debug_init_configs(debug, dir); if (rc) goto error_remove_dir; return 0; error_remove_dir: Loading
msm/dp/dp_debug.h +12 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,11 @@ pr_err("[drm:%s][msm-dp-err][%-4d]"fmt, __func__, \ current->pid, ##__VA_ARGS__) #define DEFAULT_DISCONNECT_DELAY_MS 0 #define MAX_DISCONNECT_DELAY_MS 10000 #define DEFAULT_CONNECT_NOTIFICATION_DELAY_MS 150 #define MAX_CONNECT_NOTIFICATION_DELAY_MS 5000 /** * struct dp_debug * @debug_en: specifies whether debug mode enabled Loading @@ -63,6 +68,10 @@ * @mst_sim_remove_con: specifies whether sim connector is to be removed * @mst_sim_remove_con_id: specifies id of sim connector to be removed * @mst_port_cnt: number of mst ports to be added during hpd * @connect_notification_delay_ms: time (in ms) to wait for any attention * messages before sending the connect notification uevent * @disconnect_delay_ms: time (in ms) to wait before turning off the mainlink * in response to HPD low of cable disconnect event */ struct dp_debug { bool debug_en; Loading @@ -85,6 +94,9 @@ struct dp_debug { bool mst_sim_remove_con; int mst_sim_remove_con_id; u32 mst_port_cnt; unsigned long connect_notification_delay_ms; u32 disconnect_delay_ms; struct dp_mst_connector mst_connector_cache; u8 *(*get_edid)(struct dp_debug *dp_debug); void (*abort)(struct dp_debug *dp_debug); Loading
msm/dp/dp_display.c +35 −3 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include <linux/of_irq.h> #include <linux/soc/qcom/fsa4480-i2c.h> #include <linux/usb/phy.h> #include <linux/jiffies.h> #include "sde_connector.h" Loading Loading @@ -158,6 +159,7 @@ struct dp_display_private { struct device_node *aux_switch_node; struct dentry *root; struct completion notification_comp; struct completion attention_comp; struct dp_hpd *hpd; struct dp_parser *parser; Loading Loading @@ -1026,6 +1028,8 @@ static void dp_display_host_deinit(struct dp_display_private *dp) static int dp_display_process_hpd_high(struct dp_display_private *dp) { int rc = -EINVAL; unsigned long wait_timeout_ms; unsigned long t; SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state); mutex_lock(&dp->session_lock); Loading Loading @@ -1101,7 +1105,14 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) * Delay the HPD connect notification to see if sink generates any * IRQ HPDs immediately after the HPD high. */ usleep_range(10000, 10100); reinit_completion(&dp->attention_comp); wait_timeout_ms = min_t(unsigned long, dp->debug->connect_notification_delay_ms, (unsigned long) MAX_CONNECT_NOTIFICATION_DELAY_MS); t = wait_for_completion_timeout(&dp->attention_comp, msecs_to_jiffies(wait_timeout_ms)); DP_DEBUG("wait_timeout=%lu ms, time_waited=%u ms\n", wait_timeout_ms, jiffies_to_msecs(t)); /* * If an IRQ HPD is pending, then do not send a connect notification. Loading @@ -1118,7 +1129,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) */ if (!dp->mst.mst_active && (work_busy(&dp->attention_work) == WORK_BUSY_PENDING)) { SDE_EVT32_EXTERNAL(dp->state, 99); SDE_EVT32_EXTERNAL(dp->state, 99, jiffies_to_msecs(t)); DP_DEBUG("Attention pending, skip HPD notification\n"); goto skip_notify; } Loading @@ -1127,7 +1138,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp_display_send_hpd_notification(dp); skip_notify: SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state, rc); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state, wait_timeout_ms, rc); return rc; } Loading Loading @@ -1333,6 +1345,9 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp) static void dp_display_disconnect_sync(struct dp_display_private *dp) { int disconnect_delay_ms; SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, dp->state); /* cancel any pending request */ dp_display_state_add(DP_STATE_ABORTED); Loading @@ -1344,7 +1359,22 @@ static void dp_display_disconnect_sync(struct dp_display_private *dp) cancel_work_sync(&dp->attention_work); flush_workqueue(dp->wq); /* * Delay the teardown of the mainlink for better interop experience. * It is possible that certain sinks can issue an HPD high immediately * following an HPD low as soon as they detect the mainlink being * turned off. This can sometimes result in the HPD low pulse getting * lost with certain cable. This issue is commonly seen when running * DP LL CTS test 4.2.1.3. */ disconnect_delay_ms = min_t(u32, dp->debug->disconnect_delay_ms, (u32) MAX_DISCONNECT_DELAY_MS); DP_DEBUG("disconnect delay = %d ms\n", disconnect_delay_ms); msleep(disconnect_delay_ms); dp_display_handle_disconnect(dp); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state, disconnect_delay_ms); } static int dp_display_usbpd_disconnect_cb(struct device *dev) Loading Loading @@ -1572,6 +1602,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) } else if ((dp->hpd->hpd_irq && dp_display_state_is(DP_STATE_READY)) || dp->debug->mst_hpd_sim) { queue_work(dp->wq, &dp->attention_work); complete_all(&dp->attention_comp); } else if (dp->process_hpd_connect || !dp_display_state_is(DP_STATE_CONNECTED)) { dp_display_state_remove(DP_STATE_ABORTED); Loading Loading @@ -3384,6 +3415,7 @@ static int dp_display_probe(struct platform_device *pdev) } init_completion(&dp->notification_comp); init_completion(&dp->attention_comp); dp->pdev = pdev; dp->name = "drm_dp"; Loading