Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Xiangxu Yin and committed by
Dmitry Baryshkov
6fb0cf3e c8fc7280

+66 -5
+5 -5
drivers/gpu/drm/msm/dp/dp_ctrl.c
··· 423 423 424 424 static void msm_dp_ctrl_lane_mapping(struct msm_dp_ctrl_private *ctrl) 425 425 { 426 - u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */ 426 + u32 *lane_map = ctrl->link->lane_map; 427 427 u32 ln_mapping; 428 428 429 - ln_mapping = ln_0 << LANE0_MAPPING_SHIFT; 430 - ln_mapping |= ln_1 << LANE1_MAPPING_SHIFT; 431 - ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT; 432 - ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT; 429 + ln_mapping = lane_map[0] << LANE0_MAPPING_SHIFT; 430 + ln_mapping |= lane_map[1] << LANE1_MAPPING_SHIFT; 431 + ln_mapping |= lane_map[2] << LANE2_MAPPING_SHIFT; 432 + ln_mapping |= lane_map[3] << LANE3_MAPPING_SHIFT; 433 433 434 434 msm_dp_write_link(ctrl, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING, 435 435 ln_mapping);
+60
drivers/gpu/drm/msm/dp/dp_link.c
··· 1236 1236 return frequency; 1237 1237 } 1238 1238 1239 + /* 1240 + * Always populate msm_dp_link->lane_map with 4 lanes. 1241 + * - Use DTS "data-lanes" if present; otherwise fall back to default mapping. 1242 + * - For partial definitions, fill remaining entries with unused lanes in 1243 + * ascending order. 1244 + */ 1245 + static int msm_dp_link_lane_map(struct device *dev, struct msm_dp_link *msm_dp_link) 1246 + { 1247 + struct device_node *of_node = dev->of_node; 1248 + struct device_node *endpoint; 1249 + int cnt = msm_dp_link->max_dp_lanes; 1250 + u32 tmp[DP_MAX_NUM_DP_LANES]; 1251 + u32 map[DP_MAX_NUM_DP_LANES] = {0, 1, 2, 3}; /* default 1:1 mapping */ 1252 + bool used[DP_MAX_NUM_DP_LANES] = {false}; 1253 + int i, j = 0, ret = -EINVAL; 1254 + 1255 + endpoint = of_graph_get_endpoint_by_regs(of_node, 1, -1); 1256 + if (endpoint) { 1257 + ret = of_property_read_u32_array(endpoint, "data-lanes", tmp, cnt); 1258 + if (ret) 1259 + dev_dbg(dev, "endpoint data-lanes read failed (ret=%d)\n", ret); 1260 + } 1261 + 1262 + if (ret) { 1263 + ret = of_property_read_u32_array(of_node, "data-lanes", tmp, cnt); 1264 + if (ret) { 1265 + dev_info(dev, "data-lanes not defined, set to default\n"); 1266 + goto out; 1267 + } 1268 + } 1269 + 1270 + for (i = 0; i < cnt; i++) { 1271 + if (tmp[i] >= DP_MAX_NUM_DP_LANES) { 1272 + dev_err(dev, "data-lanes[%d]=%u out of range\n", i, tmp[i]); 1273 + return -EINVAL; 1274 + } 1275 + used[tmp[i]] = true; 1276 + map[i] = tmp[i]; 1277 + } 1278 + 1279 + /* Fill the remaining entries with unused physical lanes (ascending) */ 1280 + for (i = cnt; i < DP_MAX_NUM_DP_LANES && j < DP_MAX_NUM_DP_LANES; j++) { 1281 + if (!used[j]) 1282 + map[i++] = j; 1283 + } 1284 + 1285 + out: 1286 + if (endpoint) 1287 + of_node_put(endpoint); 1288 + 1289 + dev_dbg(dev, "data-lanes count %d <%d %d %d %d>\n", cnt, map[0], map[1], map[2], map[3]); 1290 + memcpy(msm_dp_link->lane_map, map, sizeof(map)); 1291 + return 0; 1292 + } 1293 + 1239 1294 static int msm_dp_link_parse_dt(struct device *dev, struct msm_dp_link *msm_dp_link) 1240 1295 { 1241 1296 struct device_node *of_node = dev->of_node; ··· 1309 1254 msm_dp_link->max_dp_lanes = cnt; 1310 1255 else 1311 1256 msm_dp_link->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */ 1257 + 1258 + if (msm_dp_link_lane_map(dev, msm_dp_link)) { 1259 + dev_err(dev, "failed to parse data-lanes\n"); 1260 + return -EINVAL; 1261 + } 1312 1262 1313 1263 msm_dp_link->max_dp_link_rate = msm_dp_link_link_frequencies(of_node); 1314 1264 if (!msm_dp_link->max_dp_link_rate)
+1
drivers/gpu/drm/msm/dp/dp_link.h
··· 74 74 struct msm_dp_link_phy_params phy_params; 75 75 struct msm_dp_link_info link_params; 76 76 77 + u32 lane_map[DP_MAX_NUM_DP_LANES]; 77 78 u32 max_dp_lanes; 78 79 u32 max_dp_link_rate; 79 80 };