From cfaa8dfa202c8aece051aa34b01e5d0027a40eac Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Tue, 19 Nov 2019 19:14:30 -0500 Subject: [PATCH] drm/msm/dp: add support to multiple dp instances Add support to multiple dp isntances. Clean up dp-mst global state. Change-Id: Iaa88ab8c339fa0e247656024b289faa087ea0fbd Signed-off-by: Xiaowen Wu Signed-off-by: Soutrik Mukhopadhyay --- msm/dp/dp_debug.c | 76 ++++++++-------- msm/dp/dp_display.c | 206 +++++++++++++++++++++++++++++++------------- msm/dp/dp_display.h | 13 +++ msm/dp/dp_mst_drm.c | 77 ++++++----------- msm/dp/dp_pll.c | 4 + msm/sde/sde_kms.c | 12 ++- 6 files changed, 241 insertions(+), 147 deletions(-) diff --git a/msm/dp/dp_debug.c b/msm/dp/dp_debug.c index 307eb471cde8..bd4d4ca04844 100644 --- a/msm/dp/dp_debug.c +++ b/msm/dp/dp_debug.c @@ -32,6 +32,8 @@ struct dp_debug_private { char exe_mode[SZ_32]; char reg_dump[SZ_32]; + const char *name; + struct dp_hpd *hpd; struct dp_link *link; struct dp_panel *panel; @@ -1899,7 +1901,7 @@ static int dp_debug_init_mst(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs create mst_con_id failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1908,7 +1910,7 @@ static int dp_debug_init_mst(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs create mst_conn_info failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1917,7 +1919,7 @@ static int dp_debug_init_mst(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DRM_ERROR("[%s] debugfs create mst_con_add failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1926,7 +1928,7 @@ static int dp_debug_init_mst(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DRM_ERROR("[%s] debugfs create mst_con_remove failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1935,7 +1937,7 @@ static int dp_debug_init_mst(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs mst_mode failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1944,7 +1946,7 @@ static int dp_debug_init_mst(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs mst_sideband_mode failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1962,7 +1964,7 @@ static int dp_debug_init_link(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs max_bw_code failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1971,7 +1973,7 @@ static int dp_debug_init_link(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs max_pclk_khz failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -1998,7 +2000,7 @@ static int dp_debug_init_link(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs link_bw_code failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2016,7 +2018,7 @@ static int dp_debug_init_hdcp(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs hdcp_wait_sink_sync failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2025,7 +2027,7 @@ static int dp_debug_init_hdcp(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs force_encryption failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2043,7 +2045,7 @@ static int dp_debug_init_sink_caps(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs create edid_modes failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2052,7 +2054,7 @@ static int dp_debug_init_sink_caps(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs create edid_modes_mst failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2061,7 +2063,7 @@ static int dp_debug_init_sink_caps(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs edid failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2070,7 +2072,7 @@ static int dp_debug_init_sink_caps(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs dpcd failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2088,7 +2090,7 @@ static int dp_debug_init_status(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs create file failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2097,7 +2099,7 @@ static int dp_debug_init_status(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs connected failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2105,7 +2107,7 @@ static int dp_debug_init_status(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs hdr failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2113,7 +2115,7 @@ static int dp_debug_init_status(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs hdr_mst failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2121,7 +2123,7 @@ static int dp_debug_init_status(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs hdcp failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2137,7 +2139,7 @@ static int dp_debug_init_sim(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs hpd failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2145,7 +2147,7 @@ static int dp_debug_init_sim(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs sim failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2154,7 +2156,7 @@ static int dp_debug_init_sim(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs attention failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2163,7 +2165,7 @@ static int dp_debug_init_sim(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs skip_uevent failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2172,7 +2174,7 @@ static int dp_debug_init_sim(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs force_multi_func failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2190,7 +2192,7 @@ static int dp_debug_init_dsc_fec(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs dsc_feature failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2199,7 +2201,7 @@ static int dp_debug_init_dsc_fec(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs fec_feature_enable failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2216,7 +2218,7 @@ static int dp_debug_init_tpg(struct dp_debug_private *debug, struct dentry *dir) if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs tpg failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2234,7 +2236,7 @@ static int dp_debug_init_reg_dump(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs register failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2243,7 +2245,7 @@ static int dp_debug_init_reg_dump(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs dump failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2261,7 +2263,7 @@ static int dp_debug_init_feature_toggle(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs ssc_enable failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2270,7 +2272,7 @@ static int dp_debug_init_feature_toggle(struct dp_debug_private *debug, if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DP_ERR("[%s] debugfs widebus_mode failed, rc=%d\n", - DEBUG_NAME, rc); + debug->name, rc); return rc; } @@ -2288,7 +2290,7 @@ static int dp_debug_init_configs(struct dp_debug_private *debug, 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); + debug->name, rc); return rc; } debug->dp_debug.connect_notification_delay_ms = @@ -2321,14 +2323,18 @@ static int dp_debug_init(struct dp_debug *dp_debug) return 0; } - dir = debugfs_create_dir(DEBUG_NAME, NULL); + debug->name = of_get_property(debug->dev->of_node, "label", NULL); + if (!debug->name) + debug->name = DEBUG_NAME; + + dir = debugfs_create_dir(debug->name, NULL); if (IS_ERR_OR_NULL(dir)) { if (!dir) rc = -EINVAL; else rc = PTR_ERR(dir); DP_ERR("[%s] debugfs create dir failed, rc = %d\n", - DEBUG_NAME, rc); + debug->name, rc); goto error; } diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index 60fd5111eef3..afa73fa3e013 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -133,7 +133,7 @@ static char *dp_display_state_name(enum dp_display_states state) return buf; } -static struct dp_display *g_dp_display; +static struct dp_display *g_dp_display[MAX_DP_ACTIVE_DISPLAY]; #define HPD_STRING_SIZE 30 struct dp_hdcp_dev { @@ -206,6 +206,11 @@ struct dp_display_private { bool process_hpd_connect; struct notifier_block usb_nb; + + u32 cell_idx; + u32 intf_idx[DP_STREAM_MAX]; + u32 phy_idx; + u32 stream_cnt; }; static const struct dp_display_type_info dp_info = { @@ -758,6 +763,32 @@ static int dp_display_post_hw_acquire(void *data) return 0; } +static int dp_display_get_cell_info(struct dp_display_private *dp) +{ + struct device_node *of_node = dp->pdev->dev.of_node; + int i, rc; + + of_property_read_u32(of_node, + "cell-index", &dp->cell_idx); + + if (of_property_read_bool(of_node, "qcom,mst-enable")) + dp->stream_cnt = DP_STREAM_MAX; + + of_property_read_u32_index(of_node, + "qcom,intf-index", 0, &dp->intf_idx[0]); + + for (i = 1; i < dp->stream_cnt; i++) { + rc = of_property_read_u32_index(of_node, + "qcom,intf-index", i, &dp->intf_idx[i]); + if (rc) + dp->intf_idx[i] = dp->intf_idx[0] + i; + } + + of_property_read_u32(of_node, + "qcom,phy-index", &dp->phy_idx); + + return 0; +} static int dp_display_bind(struct device *dev, struct device *master, void *data) @@ -1994,8 +2025,8 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error_catalog; } - g_dp_display->is_mst_supported = dp->parser->has_mst; - g_dp_display->dsc_cont_pps = dp->parser->dsc_continuous_pps; + dp->dp_display.is_mst_supported = dp->parser->has_mst; + dp->dp_display.dsc_cont_pps = dp->parser->dsc_continuous_pps; dp->catalog = dp_catalog_get(dev, dp->parser); if (IS_ERR(dp->catalog)) { @@ -3788,6 +3819,8 @@ static int dp_display_probe(struct platform_device *pdev) struct dp_display_private *dp; const struct of_device_id *id; const struct dp_display_type_info *info; + struct dp_display *dp_display; + int index; if (!pdev || !pdev->dev.of_node) { DP_ERR("pdev not found\n"); @@ -3801,6 +3834,13 @@ static int dp_display_probe(struct platform_device *pdev) info = id->data; + index = dp_display_get_num_of_displays(); + if (index >= MAX_DP_ACTIVE_DISPLAY) { + pr_err("exceeds max dp count\n"); + rc = -EINVAL; + goto bail; + } + dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL); if (!dp) { rc = -ENOMEM; @@ -3815,6 +3855,10 @@ static int dp_display_probe(struct platform_device *pdev) memset(&dp->mst, 0, sizeof(dp->mst)); + rc = dp_display_get_cell_info(dp); + if (rc) + goto error; + rc = dp_display_create_workqueue(dp); if (rc) { DP_ERR("Failed to create workqueue\n"); @@ -3823,50 +3867,51 @@ static int dp_display_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dp); - g_dp_display = &dp->dp_display; + dp_display = &dp->dp_display; + g_dp_display[index] = dp_display; - g_dp_display->enable = dp_display_enable; - g_dp_display->post_enable = dp_display_post_enable; - g_dp_display->pre_disable = dp_display_pre_disable; - g_dp_display->disable = dp_display_disable; - g_dp_display->set_mode = dp_display_set_mode; - g_dp_display->validate_mode = dp_display_validate_mode; - g_dp_display->get_modes = dp_display_get_modes; - g_dp_display->prepare = dp_display_prepare; - g_dp_display->unprepare = dp_display_unprepare; - g_dp_display->request_irq = dp_request_irq; - g_dp_display->get_debug = dp_get_debug; - g_dp_display->post_open = NULL; - g_dp_display->post_init = dp_display_post_init; - g_dp_display->config_hdr = dp_display_config_hdr; - g_dp_display->mst_install = dp_display_mst_install; - g_dp_display->mst_uninstall = dp_display_mst_uninstall; - g_dp_display->mst_connector_install = dp_display_mst_connector_install; - g_dp_display->mst_connector_uninstall = + dp_display->enable = dp_display_enable; + dp_display->post_enable = dp_display_post_enable; + dp_display->pre_disable = dp_display_pre_disable; + dp_display->disable = dp_display_disable; + dp_display->set_mode = dp_display_set_mode; + dp_display->validate_mode = dp_display_validate_mode; + dp_display->get_modes = dp_display_get_modes; + dp_display->prepare = dp_display_prepare; + dp_display->unprepare = dp_display_unprepare; + dp_display->request_irq = dp_request_irq; + dp_display->get_debug = dp_get_debug; + dp_display->post_open = NULL; + dp_display->post_init = dp_display_post_init; + dp_display->config_hdr = dp_display_config_hdr; + dp_display->mst_install = dp_display_mst_install; + dp_display->mst_uninstall = dp_display_mst_uninstall; + dp_display->mst_connector_install = dp_display_mst_connector_install; + dp_display->mst_connector_uninstall = dp_display_mst_connector_uninstall; - g_dp_display->mst_connector_update_edid = + dp_display->mst_connector_update_edid = dp_display_mst_connector_update_edid; - g_dp_display->mst_connector_update_link_info = + dp_display->mst_connector_update_link_info = dp_display_mst_connector_update_link_info; - g_dp_display->get_mst_caps = dp_display_get_mst_caps; - g_dp_display->set_stream_info = dp_display_set_stream_info; - g_dp_display->update_pps = dp_display_update_pps; - g_dp_display->convert_to_dp_mode = dp_display_convert_to_dp_mode; - g_dp_display->mst_get_connector_info = + dp_display->get_mst_caps = dp_display_get_mst_caps; + dp_display->set_stream_info = dp_display_set_stream_info; + dp_display->update_pps = dp_display_update_pps; + dp_display->convert_to_dp_mode = dp_display_convert_to_dp_mode; + dp_display->mst_get_connector_info = dp_display_mst_get_connector_info; - g_dp_display->mst_get_fixed_topology_port = + dp_display->mst_get_fixed_topology_port = dp_display_mst_get_fixed_topology_port; - g_dp_display->wakeup_phy_layer = + dp_display->wakeup_phy_layer = dp_display_wakeup_phy_layer; - g_dp_display->set_colorspace = dp_display_setup_colospace; - g_dp_display->get_available_dp_resources = + dp_display->set_colorspace = dp_display_setup_colospace; + dp_display->get_available_dp_resources = dp_display_get_available_dp_resources; - g_dp_display->get_display_type = dp_display_get_display_type; - g_dp_display->mst_get_fixed_topology_display_type = + dp_display->get_display_type = dp_display_get_display_type; + dp_display->mst_get_fixed_topology_display_type = dp_display_mst_get_fixed_topology_display_type; - g_dp_display->is_edp = (info->display_type == DRM_MODE_CONNECTOR_eDP) ? true : false; - g_dp_display->edp_detect = dp_display_edp_detect; + dp_display->is_edp = (info->display_type == DRM_MODE_CONNECTOR_eDP) ? true : false; + dp_display->edp_detect = dp_display_edp_detect; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { @@ -3883,31 +3928,71 @@ bail: int dp_display_get_displays(void **displays, int count) { + int i; + if (!displays) { DP_ERR("invalid data\n"); return -EINVAL; } - if (count != 1) { - DP_ERR("invalid number of displays\n"); - return -EINVAL; + for (i = 0; i < MAX_DP_ACTIVE_DISPLAY && i < count; i++) { + if (!g_dp_display[i]) + break; + + displays[i] = g_dp_display[i]; } - displays[0] = g_dp_display; - return count; + return i; } int dp_display_get_num_of_displays(void) { - if (!g_dp_display) - return 0; + int i; - return 1; + for (i = 0; i < MAX_DP_ACTIVE_DISPLAY; i++) + if (!g_dp_display[i]) + break; + + return i; } int dp_display_get_num_of_streams(void) { - return DP_STREAM_MAX; + struct dp_display_private *dp; + int i, count = 0; + + for (i = 0; i < MAX_DP_ACTIVE_DISPLAY; i++) { + if (!g_dp_display[i]) + break; + + dp = container_of(g_dp_display[i], struct dp_display_private, dp_display); + + count += dp->stream_cnt; + } + + return count; +} + +int dp_display_get_info(void *dp_display, struct dp_display_info *dp_info) +{ + struct dp_display_private *dp; + int i; + + if (!dp_display) { + DP_DEBUG("dp display not initialized\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp_info->cell_idx = dp->cell_idx; + dp_info->intf_idx[0] = dp->intf_idx[0]; + for (i = 1; i < dp->stream_cnt; i++) + dp_info->intf_idx[i] = dp->intf_idx[i]; + dp_info->phy_idx = dp->phy_idx; + dp_info->stream_cnt = dp->stream_cnt; + + return 0; } static void dp_display_set_mst_state(void *dp_display, @@ -3915,16 +4000,11 @@ static void dp_display_set_mst_state(void *dp_display, { struct dp_display_private *dp; - if (!g_dp_display) { - DP_DEBUG("dp display not initialized\n"); - return; - } - - dp = container_of(g_dp_display, struct dp_display_private, dp_display); + dp = container_of(dp_display, struct dp_display_private, dp_display); SDE_EVT32_EXTERNAL(mst_state, dp->mst.mst_active); if (dp->mst.mst_active && dp->mst.cbs.set_drv_state) - dp->mst.cbs.set_drv_state(g_dp_display, mst_state); + dp->mst.cbs.set_drv_state(dp_display, mst_state); } static int dp_display_remove(struct platform_device *pdev) @@ -3949,12 +4029,16 @@ static int dp_display_remove(struct platform_device *pdev) static int dp_pm_prepare(struct device *dev) { - struct dp_display_private *dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp; + + if (!dev) + return -EINVAL; + + dp = dev_get_drvdata(dev); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY); mutex_lock(&dp->session_lock); - dp_display_set_mst_state(g_dp_display, PM_SUSPEND); + dp_display_set_mst_state(&dp->dp_display, PM_SUSPEND); /* * There are a few instances where the DP is hotplugged when the device @@ -3979,12 +4063,16 @@ static int dp_pm_prepare(struct device *dev) static void dp_pm_complete(struct device *dev) { - struct dp_display_private *dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp; + + if (!dev) + return; + + dp = dev_get_drvdata(dev); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY); mutex_lock(&dp->session_lock); - dp_display_set_mst_state(g_dp_display, PM_DEFAULT); + dp_display_set_mst_state(&dp->dp_display, PM_DEFAULT); /* * There are multiple PM suspend entry and exits observed before diff --git a/msm/dp/dp_display.h b/msm/dp/dp_display.h index 60eab0f4ee31..892322fa2fc2 100644 --- a/msm/dp/dp_display.h +++ b/msm/dp/dp_display.h @@ -15,6 +15,7 @@ #include "dp_parser.h" #define DP_MST_SIM_MAX_PORTS 8 +#define MAX_DP_ACTIVE_DISPLAY 8 enum dp_drv_state { PM_DEFAULT, @@ -31,6 +32,13 @@ struct dp_mst_hpd_info { int mst_sim_remove_con_id; }; +struct dp_display_info { + u32 cell_idx; + u32 intf_idx[DP_STREAM_MAX]; + u32 phy_idx; + u32 stream_cnt; +}; + struct dp_mst_drm_cbs { void (*hpd)(void *display, bool hpd_status); void (*hpd_irq)(void *display, struct dp_mst_hpd_info *info); @@ -146,6 +154,7 @@ struct dp_display { int dp_display_get_num_of_displays(void); int dp_display_get_displays(void **displays, int count); int dp_display_get_num_of_streams(void); +int dp_display_get_info(void *dp_display, struct dp_display_info *dp_info); #else static inline int dp_display_get_num_of_displays(void) { @@ -159,6 +168,10 @@ static inline int dp_display_get_num_of_streams(void) { return 0; } +static inline int dp_display_get_info(void *dp_display, struct dp_display_info *dp_info) +{ + return 0; +} static inline int dp_connector_update_pps(struct drm_connector *connector, char *pps_cmd, void *display) { diff --git a/msm/dp/dp_mst_drm.c b/msm/dp/dp_mst_drm.c index 1a295edeee3b..291c1207c08a 100644 --- a/msm/dp/dp_mst_drm.c +++ b/msm/dp/dp_mst_drm.c @@ -159,11 +159,6 @@ struct dp_mst_private { bool mst_session_state; }; -struct dp_mst_encoder_info_cache { - u8 cnt; - struct drm_encoder *mst_enc[MAX_DP_MST_DRM_BRIDGES]; -}; - #define to_dp_mst_bridge(x) container_of((x), struct dp_mst_bridge, base) #define to_dp_mst_bridge_priv(x) \ container_of((x), struct dp_mst_bridge, obj) @@ -172,9 +167,6 @@ struct dp_mst_encoder_info_cache { #define to_dp_mst_bridge_state(x) \ to_dp_mst_bridge_priv_state((x)->obj.state) -struct dp_mst_private dp_mst; -struct dp_mst_encoder_info_cache dp_mst_enc_cache; - static void dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) { struct dp_mst_private *mst = container_of(mgr, struct dp_mst_private, @@ -299,7 +291,7 @@ static void dp_mst_sim_add_port(struct dp_mst_private *mst, port->parent = mstb; port->port_num = port_msg->port_number; port->mgr = mstb->mgr; - port->aux.name = dp_mst.caps.drm_aux->name; + port->aux.name = mst->caps.drm_aux->name; port->aux.dev = mst->dp_display->drm_dev->dev; /* @@ -1259,19 +1251,6 @@ int dp_mst_drm_bridge_init(void *data, struct drm_encoder *encoder) struct dp_mst_private *mst = display->dp_mst_prv_info; int i; - if (!mst || !mst->mst_initialized) { - if (dp_mst_enc_cache.cnt >= MAX_DP_MST_DRM_BRIDGES) { - DP_MST_INFO("exceeding max bridge cnt %d\n", - dp_mst_enc_cache.cnt); - return 0; - } - - dp_mst_enc_cache.mst_enc[dp_mst_enc_cache.cnt] = encoder; - dp_mst_enc_cache.cnt++; - DP_MST_INFO("mst not initialized. cache encoder information\n"); - return 0; - } - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { if (!mst->mst_bridge[i].in_use) { bridge = &mst->mst_bridge[i]; @@ -2415,10 +2394,9 @@ int dp_mst_init(struct dp_display *dp_display) { struct drm_device *dev; int conn_base_id = 0; - int ret, i; + int ret; struct dp_mst_drm_install_info install_info; - - memset(&dp_mst, 0, sizeof(dp_mst)); + struct dp_mst_private *dp_mst; if (!dp_display) { DP_ERR("invalid params\n"); @@ -2427,60 +2405,57 @@ int dp_mst_init(struct dp_display *dp_display) dev = dp_display->drm_dev; + dp_mst = devm_kzalloc(dev->dev, sizeof(*dp_mst), GFP_KERNEL); + if (!dp_mst) + return -ENOMEM; + /* register with DP driver */ - install_info.dp_mst_prv_info = &dp_mst; + install_info.dp_mst_prv_info = dp_mst; install_info.cbs = &dp_mst_display_cbs; dp_display->mst_install(dp_display, &install_info); - dp_display->get_mst_caps(dp_display, &dp_mst.caps); + dp_display->get_mst_caps(dp_display, &dp_mst->caps); - if (!dp_mst.caps.has_mst) { + if (!dp_mst->caps.has_mst) { DP_MST_DEBUG("mst not supported\n"); return 0; } - dp_mst.mst_fw_cbs = &drm_dp_mst_fw_helper_ops; + dp_mst->mst_fw_cbs = &drm_dp_mst_fw_helper_ops; - memset(&dp_mst.mst_mgr, 0, sizeof(dp_mst.mst_mgr)); - dp_mst.mst_mgr.cbs = &dp_mst_drm_cbs; + memset(&dp_mst->mst_mgr, 0, sizeof(dp_mst->mst_mgr)); + dp_mst->mst_mgr.cbs = &dp_mst_drm_cbs; conn_base_id = dp_display->base_connector->base.id; - dp_mst.dp_display = dp_display; + dp_mst->dp_display = dp_display; - mutex_init(&dp_mst.mst_lock); - mutex_init(&dp_mst.edid_lock); + mutex_init(&dp_mst->mst_lock); + mutex_init(&dp_mst->edid_lock); - ret = drm_dp_mst_topology_mgr_init(&dp_mst.mst_mgr, dev, - dp_mst.caps.drm_aux, - dp_mst.caps.max_dpcd_transaction_bytes, - dp_mst.caps.max_streams_supported, + ret = drm_dp_mst_topology_mgr_init(&dp_mst->mst_mgr, dev, + dp_mst->caps.drm_aux, + dp_mst->caps.max_dpcd_transaction_bytes, + dp_mst->caps.max_streams_supported, conn_base_id); if (ret) { DP_ERR("dp drm mst topology manager init failed\n"); goto error; } - dp_mst_sim_init(&dp_mst); + dp_mst_sim_init(dp_mst); - dp_mst.mst_initialized = true; - - /* create drm_bridges for cached mst encoders and clear cache */ - for (i = 0; i < dp_mst_enc_cache.cnt; i++) { - ret = dp_mst_drm_bridge_init(dp_display, - dp_mst_enc_cache.mst_enc[i]); - } - memset(&dp_mst_enc_cache, 0, sizeof(dp_mst_enc_cache)); + dp_mst->mst_initialized = true; /* choose fixed callback function if fixed topology is found */ if (!dp_display->mst_get_fixed_topology_port(dp_display, 0, NULL)) - dp_mst.mst_mgr.cbs = &dp_mst_fixed_drm_cbs; + dp_mst->mst_mgr.cbs = &dp_mst_fixed_drm_cbs; DP_MST_INFO("dp drm mst topology manager init completed\n"); return ret; error: - mutex_destroy(&dp_mst.mst_lock); - mutex_destroy(&dp_mst.edid_lock); + mutex_destroy(&dp_mst->mst_lock); + mutex_destroy(&dp_mst->edid_lock); return ret; } @@ -2502,7 +2477,7 @@ void dp_mst_deinit(struct dp_display *dp_display) drm_dp_mst_topology_mgr_destroy(&mst->mst_mgr); - dp_mst.mst_initialized = false; + mst->mst_initialized = false; mutex_destroy(&mst->mst_lock); mutex_destroy(&mst->edid_lock); diff --git a/msm/dp/dp_pll.c b/msm/dp/dp_pll.c index 2c1f6a8b9e50..19d982284407 100644 --- a/msm/dp/dp_pll.c +++ b/msm/dp/dp_pll.c @@ -124,6 +124,10 @@ struct dp_pll *dp_pll_get(struct dp_pll_in *in) goto error; } + pll->name = of_get_property(pdev->dev.of_node, "label", NULL); + if (!pll->name) + pll->name = "dp0"; + pll->ssc_en = of_property_read_bool(pdev->dev.of_node, "qcom,ssc-feature-enable"); pll->bonding_en = of_property_read_bool(pdev->dev.of_node, diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 4eea06bff77e..308200bd8579 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1926,6 +1926,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, for (i = 0; i < sde_kms->dp_display_count && priv->num_encoders < max_encoders; ++i) { int idx; + struct dp_display_info dp_info = {0}; display = sde_kms->dp_displays[i]; encoder = NULL; @@ -1937,6 +1938,13 @@ static int _sde_kms_setup_displays(struct drm_device *dev, continue; } + rc = dp_display_get_info(display, &dp_info); + if (rc) { + SDE_ERROR("failed to read dp info, %d\n", rc); + continue; + } + + info.h_tile_instance[0] = dp_info.intf_idx[0]; encoder = sde_encoder_init(dev, &info); if (IS_ERR_OR_NULL(encoder)) { SDE_ERROR("dp encoder init failed %d\n", i); @@ -1970,9 +1978,9 @@ static int _sde_kms_setup_displays(struct drm_device *dev, /* update display cap to MST_MODE for DP MST encoders */ info.capabilities |= MSM_DISPLAY_CAP_MST_MODE; - for (idx = 0; idx < sde_kms->dp_stream_count && + for (idx = 0; idx < dp_info.stream_cnt && priv->num_encoders < max_encoders; idx++) { - info.h_tile_instance[0] = idx; + info.h_tile_instance[0] = dp_info.intf_idx[idx]; encoder = sde_encoder_init(dev, &info); if (IS_ERR_OR_NULL(encoder)) { SDE_ERROR("dp mst encoder init failed %d\n", i);