TC358762 can generate the DPI output's timings in two ways, either Video Timings Generator (VTG) on or off: - VTG off: Duplicate the timings coming from the DSI. This requires DSI pulse mode. - VTG on: Sync frame on DSI VSync Start, but the exact output timings are defined in TC358762 registers. This can be used with DSI event/burst mode.
We are currently using VTG off in the driver. I observe that the hsync signal, on my HW setup, is not 100% stable with VTG off, and it seems to lengthen by a single clock every now and then. However, it then stabilizes later. To me the DSI input looks solid, but that is more challenging to measure exactly. So I have not found the root cause for this. Turning VTG on removes that instability. As I dont' see any downsides with enabling VTG (and it would allow extending the driver to use event/burst mode in the future), let's always enable the VTG. Signed-off-by: Tomi Valkeinen <[email protected]> --- drivers/gpu/drm/bridge/tc358762.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index c5734c4df440..2d9491e8e582 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -19,6 +19,7 @@ #include <linux/regulator/consumer.h> #include <video/mipi_display.h> +#include <video/videomode.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> @@ -64,6 +65,12 @@ #define LCDCTRL_VSYNC_POL BIT(19) /* Polarity of VSYNC signal */ #define LCDCTRL_DCLK_POL BIT(20) /* Polarity of pixel clock */ +#define LCDC_HSR_HBPR 0x0424 +#define LCDC_HDISPR_HFPR 0x0428 +#define LCDC_VSR_VBPR 0x042C +#define LCDC_VDISPR_VFPR 0x0430 +#define LCDC_VFUEN 0x0434 + /* SPI Master Registers */ #define SPICMR 0x0450 #define SPITCR 0x0454 @@ -95,6 +102,7 @@ struct tc358762 { struct drm_display_mode mode; bool pre_enabled; int error; + bool use_vtg; }; static int tc358762_clear_error(struct tc358762 *ctx) @@ -156,9 +164,31 @@ static int tc358762_init(struct tc358762 *ctx) tc358762_write(ctx, PPI_D1S_ATMR, 0); tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD); + if (ctx->use_vtg) { + struct videomode vm = { 0 }; + + drm_display_mode_to_videomode(&ctx->mode, &vm); + + tc358762_write(ctx, LCDC_HSR_HBPR, + vm.hsync_len | (vm.hback_porch << 16)); + tc358762_write(ctx, LCDC_HDISPR_HFPR, + vm.hactive | (vm.hfront_porch << 16)); + + tc358762_write(ctx, LCDC_VSR_VBPR, + vm.vsync_len | (vm.vback_porch << 16)); + tc358762_write(ctx, LCDC_VDISPR_VFPR, + vm.vactive | (vm.vfront_porch << 16)); + + /* Upload VTG timings */ + tc358762_write(ctx, LCDC_VFUEN, BIT(0)); + } + lcdctrl = FIELD_PREP(LCDCTRL_PXLFORM, LCDCTRL_PXLFORM_RGB888) | LCDCTRL_DPI_EN; + if (ctx->use_vtg) + lcdctrl |= LCDCTRL_VTGEN; + lcdctrl |= LCDCTRL_DCLK_POL; if (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC) @@ -306,6 +336,9 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) ctx->dev = dev; ctx->pre_enabled = false; + /* Always use VTG */ + ctx->use_vtg = true; + /* * When using DSI clk for pixel clock (only mode supported in the driver), * the pclk is derived directly from the DSI byteclk via simple divider, -- 2.43.0
