From 793f858ef26565e5aac924a4b4e87f63a22b49ae Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Wed, 17 Apr 2024 14:15:42 +0800 Subject: [PATCH] drm/rockchip: dw-dp: support fix stream and connector The DP Port may attach a DP MST bridge device as follow: +-------------------------+ +---------------------------------+ | | | | | +---------+ | | +-------------+ | | | | | | | | | stream0 | | | | Output Port1| | | | | | | | | +---------+ | | +-------------+ | | | | | | | | | +---------+ | +-------------+ +-------------+ | | | | | | | | | DP Port | stream1 | +------> Input Port0 | | Output Port2| | | | | | | | | | +---------+ | +-------------+ +-------------+ | | | | | | | | | +---------+ | | +-------------+ | | | | | | | | | stream2 | | | | Output Port3| | | | | | | | | +---------+ | | +-------------+ | | | DP MST Bridge | +-------------------------+ +---------------------------------+ The DP MST bridge device may be a branch device, such as DP MST HUB, the branch unit in DP MST monitor, A DP MST bridge chip and so on. When a sink device connected to the DP MST bridege device's output port, The sink device may receive the stream from steram0/1/2. When the DP MST bridge device is a bridge chip and the output port attach to a fixed device(another bridge device or panel). The output port may want bind itself to a fixed stream. To satisfy this requirement, The prop "rockchip,mst-fixed-ports" is used to do it. For example, define as follow: rockchip,mst-fixed-ports = <1 2 3>; It mean that: DP Port stream0 --> DP MST bridge Output Port1 DP Port stream1 --> DP MST bridge Output Port2 DP Port stream2 --> DP MST bridge Output Port3 Change-Id: I91dfc51a5e8a533ebbabdcae572163907ec2c9fe Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/dw-dp.c | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index 7ece490e33fa..48ef798f426d 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -424,6 +424,7 @@ struct dw_dp_mst_enc { struct dw_dp_mst_conn *mst_conn; struct dw_dp *dp; int stream_id; + int fix_port_num; bool active; }; @@ -488,6 +489,7 @@ struct dw_dp { bool is_loader_protect; bool support_mst; bool is_mst; + bool is_fix_port; int mst_port_num; int active_mst_links; struct drm_dp_mst_topology_mgr mst_mgr; @@ -1306,6 +1308,7 @@ static int dw_dp_mst_info_dump(struct seq_file *s, void *data) struct dw_dp *dp = node->info_ent->data; struct dw_dp_mst_conn *mst_conn; struct drm_property_blob *path_blob; + int i; if (dp->mst_mgr.cbs) { drm_dp_mst_dump_topology(s, &dp->mst_mgr); @@ -1321,6 +1324,17 @@ static int dw_dp_mst_info_dump(struct seq_file *s, void *data) (char *)path_blob->data); } seq_puts(s, "\n"); + if (dp->is_fix_port) { + seq_puts(s, "\n*** Fix port info ***\n"); + seq_puts(s, "stream id | port num\n"); + + for (i = 0; i < dp->mst_port_num; i++) { + if (!dp->mst_enc[i].dp) + continue; + seq_printf(s, "%-16d %d\n", dp->mst_enc[i].stream_id, + dp->mst_enc[i].fix_port_num); + } + } } return 0; @@ -3924,6 +3938,8 @@ dw_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_p for (i = 0; i < dp->mst_port_num; i++) { if (!of_device_is_available(dp->mst_enc[i].port_node)) continue; + if (dp->is_fix_port && dp->mst_enc[i].fix_port_num != port->port_num) + continue; ret = drm_connector_attach_encoder(&mst_conn->connector, &dp->mst_enc[i].encoder); if (ret) goto err; @@ -3979,6 +3995,31 @@ dw_dp_create_fake_mst_encoders(struct dw_dp *dp) return true; } +static int dw_dp_mst_get_fix_port(struct dw_dp *dp) +{ + char *prop_name = "rockchip,mst-fixed-ports"; + int elem_len, ret, i; + int elem_data[DPTX_MAX_STREAMS]; + + if (!device_property_present(dp->dev, prop_name)) + return 0; + + elem_len = device_property_count_u32(dp->dev, prop_name); + if (dp->mst_port_num != elem_len) + return -EINVAL; + + ret = device_property_read_u32_array(dp->dev, prop_name, elem_data, elem_len); + if (ret) + return -EINVAL; + + dp->is_fix_port = true; + + for (i = 0; i < dp->mst_port_num; i++) + dp->mst_enc[i].fix_port_num = elem_data[i]; + + return 0; +} + static int dw_dp_mst_encoder_init(struct dw_dp *dp, int conn_base_id) { int ret; @@ -3989,6 +4030,10 @@ static int dw_dp_mst_encoder_init(struct dw_dp *dp, int conn_base_id) INIT_LIST_HEAD(&dp->mst_conn_list); dp->mst_mgr.cbs = &mst_cbs; dw_dp_create_fake_mst_encoders(dp); + ret = dw_dp_mst_get_fix_port(dp); + if (ret) + return ret; + ret = drm_dp_mst_topology_mgr_init(&dp->mst_mgr, dp->encoder.dev, &dp->aux, 16, dp->mst_port_num, conn_base_id); if (ret)