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 <wxiaowen@codeaurora.org>
Signed-off-by: Soutrik Mukhopadhyay <quic_mukhopad@quicinc.com>
This commit is contained in:
Xiaowen Wu 2019-11-19 19:14:30 -05:00 • committed by Gerrit - the friendly Code Review server
commit cfaa8dfa20
6 changed files with 241 additions and 147 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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)
{

View file

@ -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);

View file

@ -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,

View file

@ -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);