mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 12:03:54 +02:00
drm/msm/dp: Add support for lane mapping configuration
QCS615 platform requires non-default logical-to-physical lane mapping due to its unique hardware routing. Unlike the standard mapping sequence <0 1 2 3>, QCS615 uses <3 2 0 1>, which necessitates explicit configuration via the data-lanes property in the device tree. This ensures correct signal routing between the DP controller and PHY. For partial definitions, fill remaining lanes with unused physical lanes in ascending order. Signed-off-by: Xiangxu Yin <xiangxu.yin@oss.qualcomm.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Patchwork: https://patchwork.freedesktop.org/patch/675645/ Link: https://lore.kernel.org/r/20250919-add-displayport-support-for-qcs615-platform-v5-14-eae6681f4002@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
This commit is contained in:
parent
c8fc72804d
commit
6fb0cf3e7c
|
|
@ -423,13 +423,13 @@ static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl)
|
|||
|
||||
static void msm_dp_ctrl_lane_mapping(struct msm_dp_ctrl_private *ctrl)
|
||||
{
|
||||
u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */
|
||||
u32 *lane_map = ctrl->link->lane_map;
|
||||
u32 ln_mapping;
|
||||
|
||||
ln_mapping = ln_0 << LANE0_MAPPING_SHIFT;
|
||||
ln_mapping |= ln_1 << LANE1_MAPPING_SHIFT;
|
||||
ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT;
|
||||
ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT;
|
||||
ln_mapping = lane_map[0] << LANE0_MAPPING_SHIFT;
|
||||
ln_mapping |= lane_map[1] << LANE1_MAPPING_SHIFT;
|
||||
ln_mapping |= lane_map[2] << LANE2_MAPPING_SHIFT;
|
||||
ln_mapping |= lane_map[3] << LANE3_MAPPING_SHIFT;
|
||||
|
||||
msm_dp_write_link(ctrl, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING,
|
||||
ln_mapping);
|
||||
|
|
|
|||
|
|
@ -1236,6 +1236,61 @@ static u32 msm_dp_link_link_frequencies(struct device_node *of_node)
|
|||
return frequency;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always populate msm_dp_link->lane_map with 4 lanes.
|
||||
* - Use DTS "data-lanes" if present; otherwise fall back to default mapping.
|
||||
* - For partial definitions, fill remaining entries with unused lanes in
|
||||
* ascending order.
|
||||
*/
|
||||
static int msm_dp_link_lane_map(struct device *dev, struct msm_dp_link *msm_dp_link)
|
||||
{
|
||||
struct device_node *of_node = dev->of_node;
|
||||
struct device_node *endpoint;
|
||||
int cnt = msm_dp_link->max_dp_lanes;
|
||||
u32 tmp[DP_MAX_NUM_DP_LANES];
|
||||
u32 map[DP_MAX_NUM_DP_LANES] = {0, 1, 2, 3}; /* default 1:1 mapping */
|
||||
bool used[DP_MAX_NUM_DP_LANES] = {false};
|
||||
int i, j = 0, ret = -EINVAL;
|
||||
|
||||
endpoint = of_graph_get_endpoint_by_regs(of_node, 1, -1);
|
||||
if (endpoint) {
|
||||
ret = of_property_read_u32_array(endpoint, "data-lanes", tmp, cnt);
|
||||
if (ret)
|
||||
dev_dbg(dev, "endpoint data-lanes read failed (ret=%d)\n", ret);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
ret = of_property_read_u32_array(of_node, "data-lanes", tmp, cnt);
|
||||
if (ret) {
|
||||
dev_info(dev, "data-lanes not defined, set to default\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (tmp[i] >= DP_MAX_NUM_DP_LANES) {
|
||||
dev_err(dev, "data-lanes[%d]=%u out of range\n", i, tmp[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
used[tmp[i]] = true;
|
||||
map[i] = tmp[i];
|
||||
}
|
||||
|
||||
/* Fill the remaining entries with unused physical lanes (ascending) */
|
||||
for (i = cnt; i < DP_MAX_NUM_DP_LANES && j < DP_MAX_NUM_DP_LANES; j++) {
|
||||
if (!used[j])
|
||||
map[i++] = j;
|
||||
}
|
||||
|
||||
out:
|
||||
if (endpoint)
|
||||
of_node_put(endpoint);
|
||||
|
||||
dev_dbg(dev, "data-lanes count %d <%d %d %d %d>\n", cnt, map[0], map[1], map[2], map[3]);
|
||||
memcpy(msm_dp_link->lane_map, map, sizeof(map));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_dp_link_parse_dt(struct device *dev, struct msm_dp_link *msm_dp_link)
|
||||
{
|
||||
struct device_node *of_node = dev->of_node;
|
||||
|
|
@ -1255,6 +1310,11 @@ static int msm_dp_link_parse_dt(struct device *dev, struct msm_dp_link *msm_dp_l
|
|||
else
|
||||
msm_dp_link->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */
|
||||
|
||||
if (msm_dp_link_lane_map(dev, msm_dp_link)) {
|
||||
dev_err(dev, "failed to parse data-lanes\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msm_dp_link->max_dp_link_rate = msm_dp_link_link_frequencies(of_node);
|
||||
if (!msm_dp_link->max_dp_link_rate)
|
||||
msm_dp_link->max_dp_link_rate = DP_LINK_RATE_HBR2;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ struct msm_dp_link {
|
|||
struct msm_dp_link_phy_params phy_params;
|
||||
struct msm_dp_link_info link_params;
|
||||
|
||||
u32 lane_map[DP_MAX_NUM_DP_LANES];
|
||||
u32 max_dp_lanes;
|
||||
u32 max_dp_link_rate;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user