Re: [PATCH v6] drm/omap: dsi: avoid sending bta sync all the time in writes
Ivaylo Dimitrov <[email protected]> Wed, 5 Aug 2026 10:33:52 +0300
| Newsgroups | gmane.linux.kernel,gmane.linux.ports.arm.omap,gmane.comp.video.dri.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi,
On 4.08.26 г. 11:37 ч., Andreas Kemnade wrote:
> Some chips need configuration commands to be sent first, before they can
> send data. TC358762 for example needs PPI_LPTXTIMECNT configured
> and PPI_STARTPPI set to 1 to be able to transmit anything. To be able to
> configure such chips, do not send bta sync during writes if no acks are
> requested. Instead just wait for the packet to be sent to avoid FIFO
> overflows. There might be more to do about acks, but there seem to be
> virtually no users of that flag.
>
> This came to light when fiddling with the Epson Moverio BT-200 display
> which consists of 2 TC358762 bridges with SPI funneled through
> to the unknown display chip. With that patch the bridge can be accessed,
> Reading back registers works, when the above-mentioned registers are set.
>
> In Command-Mode update, there was a nop sent, apparently the most
> relevant part was the bta sync to actually force low power mode.
>
> Video mode panel at OMAP4 (BT-200) and video mode at OMAP5 was tested.
>
> Fixes: e70965386353e ("drm/omap: dsi: simplify write function")
> Signed-off-by: Andreas Kemnade <[email protected]>
Tested on motorolla droid4 (command mode), no visible issues so far.
> ---
> Changes in v6:
> - clear errors on every write
> - remove unneeded forward declaration
>
> Changes in v5:
> - send bta sync on VC_CMD again
> - Link to v4: https://patch.msgid.link/[email protected]
>
> Changes in v4:
> - wait on completition on all packets (was limited to long packets only,
> because I had the wrong impression that there is no confirmation on
> these)
> - Link to v3: https://patch.msgid.link/[email protected]
>
> Changes in v3:
>
> - Link to v2: https://patch.msgid.link/[email protected]
> - fix things mentioned by claude here:
> https://lore.gitlab.freedesktop.org/drm-ai-reviews/[email protected]/
> - fix typos
> - register ISR before sending packet
> - check for RX_FIFO_NOT_EMPTY also in for short packets
>
> Changes in v2:
> - fix commandmode update, need bta sync there
> - do not wait on short packets
> - Link to v1: https://patch.msgid.link/[email protected]
>
> To: Tomi Valkeinen <[email protected]>
> To: Maarten Lankhorst <[email protected]>
> To: Maxime Ripard <[email protected]>
> To: Thomas Zimmermann <[email protected]>
> To: David Airlie <[email protected]>
> To: Simona Vetter <[email protected]>
> To: Laurent Pinchart <[email protected]>
> To: Sebastian Reichel <[email protected]>
> Cc: Tomi Valkeinen <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> ---
> drivers/gpu/drm/omapdrm/dss/dsi.c | 63 +++++++++++++++++++--------------------
> 1 file changed, 31 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
> index 27fe7bca9e2c..27bf9bbe0697 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dsi.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
> @@ -58,9 +58,6 @@ static void dsi_uninit_dispc(struct dsi_data *dsi);
>
> static int dsi_vc_send_null(struct dsi_data *dsi, int vc, int channel);
>
> -static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi, int vc,
> - const struct mipi_dsi_msg *msg);
> -
> #ifdef DSI_PERF_MEASURE
> static bool dsi_perf;
> module_param(dsi_perf, bool, 0644);
> @@ -2194,28 +2191,45 @@ static int dsi_vc_send_null(struct dsi_data *dsi, int vc, int channel)
> static int dsi_vc_write_common(struct omap_dss_device *dssdev, int vc,
> const struct mipi_dsi_msg *msg)
> {
> + DECLARE_COMPLETION_ONSTACK(completion);
> struct dsi_data *dsi = to_dsi_data(dssdev);
> + u32 err;
> int r;
>
> + /* wait for IRQ for packet transmission confirmation */
> + r = dsi_register_isr_vc(dsi, vc, dsi_completion_handler,
> + &completion, DSI_VC_IRQ_PACKET_SENT);
> + if (r)
> + return r;
> +
> if (mipi_dsi_packet_format_is_short(msg->type))
> r = dsi_vc_send_short(dsi, vc, msg);
> else
> r = dsi_vc_send_long(dsi, vc, msg);
>
> - if (r < 0)
> + if ((!r) && wait_for_completion_timeout(&completion,
> + msecs_to_jiffies(500)) == 0)
> + r = -EIO;
> +
> + dsi_unregister_isr_vc(dsi, vc, dsi_completion_handler,
> + &completion, DSI_VC_IRQ_PACKET_SENT);
> + if (r)
> return r;
>
> - /*
> - * TODO: we do not always have to do the BTA sync, for example
> - * we can improve performance by setting the update window
> - * information without sending BTA sync between the commands.
> - * In that case we can return early.
> - */
> + /* TODO: find out if more needs to be done for MIPI_DSI_MSG_REQ_ACK */
>
> - r = dsi_vc_send_bta_sync(dssdev, vc);
> - if (r) {
> - DSSERR("bta sync failed\n");
> - return r;
> + if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
> + r = dsi_vc_send_bta_sync(dssdev, vc);
> + if (r) {
> + DSSERR("bta sync failed\n");
> + return r;
> + }
> + } else {
> + err = dsi_get_errors(dsi);
> + if (err) {
> + DSSERR("Error while sending: %x\n", err);
> + return -EIO;
> + }
> }
>
> /* RX_FIFO_NOT_EMPTY */
> @@ -3233,21 +3247,6 @@ static int _dsi_update(struct dsi_data *dsi)
> return 0;
> }
>
> -static int _dsi_send_nop(struct dsi_data *dsi, int vc, int channel)
> -{
> - const u8 payload[] = { MIPI_DCS_NOP };
> - const struct mipi_dsi_msg msg = {
> - .channel = channel,
> - .type = MIPI_DSI_DCS_SHORT_WRITE,
> - .tx_len = 1,
> - .tx_buf = payload,
> - };
> -
> - WARN_ON(!dsi_bus_is_locked(dsi));
> -
> - return _omap_dsi_host_transfer(dsi, vc, &msg);
> -}
> -
> static int dsi_update_channel(struct omap_dss_device *dssdev, int vc)
> {
> struct dsi_data *dsi = to_dsi_data(dssdev);
> @@ -3268,13 +3267,13 @@ static int dsi_update_channel(struct omap_dss_device *dssdev, int vc)
> DSSDBG("dsi_update_channel: %d", vc);
>
> /*
> - * Send NOP between the frames. If we don't send something here, the
> + * Transition to LP here. If we don't send something here, the
> * updates stop working. This is probably related to DSI spec stating
> * that the DSI host should transition to LP at least once per frame.
> */
> - r = _dsi_send_nop(dsi, VC_CMD, dsi->dsidev->channel);
> + r = dsi_vc_send_bta_sync(dssdev, VC_CMD);
> if (r < 0) {
> - DSSWARN("failed to send nop between frames: %d\n", r);
> + DSSWARN("failed to send bta sync between frames: %d\n", r);
> goto err;
> }
>
>
> ---
> base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
> change-id: 20260528-vm-upstr-c8e7634ebf56
>
> Best regards,
> --
> Andreas Kemnade <[email protected]>
>