This adds support for using SN65DSI84 in single-link mode with output to LVDS Channel B.
Signed-off-by: Esben Haabendal <es...@geanix.com> --- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index 95563aa1b450d549be8cacbe58c45f07b93595e5..e5785447c804eeced24f80c2b8b90283623c86a9 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -11,6 +11,8 @@ * = 1x Single-link DSI ~ 2x Single-link or 1x Dual-link LVDS * - Supported * - Dual-link LVDS mode tested + * - Single-link to LVDS Channel A tested. + * - Single-link to LVDS Channel B tested. * - 2x Single-link LVDS mode unsupported * (should be easy to add by someone who has the HW) * - SN65DSI85 @@ -158,7 +160,7 @@ struct sn65dsi83 { struct gpio_desc *enable_gpio; struct regulator *vcc; bool lvds_dual_link; - bool lvds_dual_link_even_odd_swap; + bool lvds_channel_swap; int lvds_vod_swing_conf[2]; int lvds_term_conf[2]; int irq; @@ -587,7 +589,7 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, REG_LVDS_VCOM_CHA_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_A]) | REG_LVDS_VCOM_CHB_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_B])); regmap_write(ctx->regmap, REG_LVDS_LANE, - (ctx->lvds_dual_link_even_odd_swap ? + (ctx->lvds_channel_swap ? REG_LVDS_LANE_EVEN_ODD_SWAP : 0) | (ctx->lvds_term_conf[CHANNEL_A] ? REG_LVDS_LANE_CHA_LVDS_TERM : 0) | @@ -834,6 +836,7 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model) { struct drm_bridge *panel_bridge; struct device *dev = ctx->dev; + u32 panel_port = 2; int ret; ret = sn65dsi83_parse_lvds_endpoint(ctx, CHANNEL_A); @@ -845,29 +848,38 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model) return ret; ctx->lvds_dual_link = false; - ctx->lvds_dual_link_even_odd_swap = false; + ctx->lvds_channel_swap = false; if (model != MODEL_SN65DSI83) { - struct device_node *port2, *port3; + struct device_node *port0, *port1, *port2, *port3; int dual_link; + port0 = of_graph_get_port_by_id(dev->of_node, 0); + port1 = of_graph_get_port_by_id(dev->of_node, 1); port2 = of_graph_get_port_by_id(dev->of_node, 2); port3 = of_graph_get_port_by_id(dev->of_node, 3); dual_link = drm_of_lvds_get_dual_link_pixel_order(port2, port3); - of_node_put(port2); - of_node_put(port3); if (dual_link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) { - ctx->lvds_dual_link = true; /* Odd pixels to LVDS Channel A, even pixels to B */ - ctx->lvds_dual_link_even_odd_swap = false; - } else if (dual_link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) { ctx->lvds_dual_link = true; + } else if (dual_link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) { /* Even pixels to LVDS Channel A, odd pixels to B */ - ctx->lvds_dual_link_even_odd_swap = true; + ctx->lvds_dual_link = true; + ctx->lvds_channel_swap = true; + } else if (port0 && !port1 && port2 && !port3) { + /* DSI Channel A to LVDS Channel A */ + } else if (port0 && !port1 && !port2 && port3) { + /* DSI Channel A to LVDS Channel B */ + ctx->lvds_channel_swap = true; + panel_port = 3; } + of_node_put(port0); + of_node_put(port1); + of_node_put(port2); + of_node_put(port3); } - panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0); + panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, panel_port, 0); if (IS_ERR(panel_bridge)) return dev_err_probe(dev, PTR_ERR(panel_bridge), "Failed to get panel bridge\n"); --- base-commit: b4432656b36e5cc1d50a1f2dc15357543add530e change-id: 20250430-sn65dsi83-channel-swap-f73afc78ace8 Best regards, -- Esben Haabendal <es...@geanix.com>