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

Configure Feed

Select the types of activity you want to include in your feed.

drm/bridge: ti-sn65dsi83: halve horizontal syncs for dual LVDS output

Dual LVDS output (available on the SN65DSI84) requires HSYNC_PULSE_WIDTH
and HORIZONTAL_BACK_PORCH to be divided by two with respect to the values
used for single LVDS output.

While not clearly stated in the datasheet, this is needed according to the
DSI Tuner [0] output. It also makes sense intuitively because in dual LVDS
output two pixels at a time are output and so the output clock is half of
the pixel clock.

Some dual-LVDS panels refuse to show any picture without this fix.

Divide by two HORIZONTAL_FRONT_PORCH too, even though this register is used
only for test pattern generation which is not currently implemented by this
driver.

[0] https://www.ti.com/tool/DSI-TUNER

Fixes: ceb515ba29ba ("drm/bridge: ti-sn65dsi83: Add TI SN65DSI83 and SN65DSI84 driver")
Cc: stable@vger.kernel.org
Reviewed-by: Marek Vasut <marek.vasut@mailbox.org>
Link: https://patch.msgid.link/20260226-ti-sn65dsi83-dual-lvds-fixes-and-test-pattern-v1-2-2e15f5a9a6a0@bootlin.com
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>

+4 -3
+4 -3
drivers/gpu/drm/bridge/ti-sn65dsi83.c
··· 517 517 struct drm_atomic_state *state) 518 518 { 519 519 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); 520 + const unsigned int dual_factor = ctx->lvds_dual_link ? 2 : 1; 520 521 const struct drm_bridge_state *bridge_state; 521 522 const struct drm_crtc_state *crtc_state; 522 523 const struct drm_display_mode *mode; ··· 654 653 /* 32 + 1 pixel clock to ensure proper operation */ 655 654 le16val = cpu_to_le16(32 + 1); 656 655 regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2); 657 - le16val = cpu_to_le16(mode->hsync_end - mode->hsync_start); 656 + le16val = cpu_to_le16((mode->hsync_end - mode->hsync_start) / dual_factor); 658 657 regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW, 659 658 &le16val, 2); 660 659 le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start); 661 660 regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW, 662 661 &le16val, 2); 663 662 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH, 664 - mode->htotal - mode->hsync_end); 663 + (mode->htotal - mode->hsync_end) / dual_factor); 665 664 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH, 666 665 mode->vtotal - mode->vsync_end); 667 666 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH, 668 - mode->hsync_start - mode->hdisplay); 667 + (mode->hsync_start - mode->hdisplay) / dual_factor); 669 668 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH, 670 669 mode->vsync_start - mode->vdisplay); 671 670 regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00);