From nobody Tue Apr 7 02:35:30 2026 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 708B63B47D7 for ; Wed, 11 Mar 2026 07:49:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773215352; cv=none; b=HT+Y38MUb8bso7Z7uxTuYupSQH+I6FHofU7fmdheGPp0vs55EjyH/FYHjH4zkQYa/nllCIxE8Jss3ZbKOcoEgo1MQS8KpO2lzpvCMoTTi1vyYiky7eiasxeTB1b79EYg0MrYYusQ7f1fED7i1sSq8pHjSPakUS8qSmS9cDO+sXg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773215352; c=relaxed/simple; bh=Zqy+ABHtxCCk9RIcVVNFOD+Evri8uLJ6LK1kWuU4n1Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kYSij1T8vhKVZtqga+P6RVykcAO2Tta6hF5oXiMW2FdU2BCsl08UNaSYD2d0ZpbCi1+G/Pbj7mLwW83JR4zNqfBhEzNpRBVizOQexmMOXl1fy9Jc+u2pgkwHhwm8IPM7oAraxo8O7AjC1DWac92d2m/YsUrzgqeXGVgsqLR5N6c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=a2EBKXHy; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="a2EBKXHy" Received: from [127.0.1.1] (91-158-153-178.elisa-laajakaista.fi [91.158.153.178]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8960B191A; Wed, 11 Mar 2026 08:47:36 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1773215257; bh=Zqy+ABHtxCCk9RIcVVNFOD+Evri8uLJ6LK1kWuU4n1Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=a2EBKXHyaUIy6iQwwL1o7Xpb+dQtk6a0d8CGWx7icwVjs03gnXVIoPpJUrAfKjEJb PvL+InJgmUPIDwPX9IWpq7iqpGNGZcSc7KzW3e7t2ZOqDNYzUi9EjiuksL432gfA9t MtrXkc67UjVc5qFOiev7XEe9E8bq5/f1rinwHl00= From: Tomi Valkeinen Date: Wed, 11 Mar 2026 09:48:18 +0200 Subject: [PATCH v2 7/7] drm/bridge: tc358768: Add support for long command tx via video buffer Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260311-tc358768-v2-7-e75a99131bd5@ideasonboard.com> References: <20260311-tc358768-v2-0-e75a99131bd5@ideasonboard.com> In-Reply-To: <20260311-tc358768-v2-0-e75a99131bd5@ideasonboard.com> To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Parth Pancholi , Francesco Dolcini Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, Tomi Valkeinen , =?utf-8?q?Jo=C3=A3o_Paulo_Gon=C3=A7alves?= X-Mailer: b4 0.15-dev-c25d1 X-Developer-Signature: v=1; a=openpgp-sha256; l=5053; i=tomi.valkeinen@ideasonboard.com; h=from:subject:message-id; bh=Zqy+ABHtxCCk9RIcVVNFOD+Evri8uLJ6LK1kWuU4n1Y=; b=owEBbQKS/ZANAwAIAfo9qoy8lh71AcsmYgBpsR5UmdZQQUKfmeF3nNyLgYhRBZ2YC7FZ5zuk8 AY9gVRHkZCJAjMEAAEIAB0WIQTEOAw+ll79gQef86f6PaqMvJYe9QUCabEeVAAKCRD6PaqMvJYe 9SeEEACGSZ6AAwaXrpDvbOg0luyW3G5BmcN/Sl9CWmX6IPLfW1+exyE+blWfFgUU0plpuKbd6dq rggyxmae3tlYaXNFBwDHiT9JmYFiBSjTvinujbGy1ekUe29oX7yRnicSC83g0Eqsm1huEQmK8Ub H4nxnn8lDFmSQbB45Vbbsq59PUYqK0xW7rCR0tI1G7AxZP4zVUWYBoQqgR5E9gWPvhKCKQ26b07 gKoyooqPrC+nDbEEE6fwopUg6vRt0+3S7/qJIvgOc+/TGQybbmQb0x1eTOO7vEOX0To76sUzTTV ZwFUPoiq2NRqgEXR6EB46UJKDiCaHEGnKe0bEsozileBVm3gdma4ghj1pWiLq64mGiNQzMhr3jS zb0RWZKKXPLHm4G5BV2jVDsNnM/7H+tTauayAP+mKrCDkjFF9kiD/zpx6YfWlFpD2btIa03JsIE brMZyiOU/njtbZrCmk7uRBmPcXPpr0tm+ygBp9Q4RV57PuMpcxAjUhcAeELga7Dk46+sjOa8bz2 9p9aOSrB3nqpcgjHNdz4+DnRb4Tr9E6sEKVmxzK4BuqWQ2fN3Oi7BT35CbzU9oWgYNHdXajfABt zK2W0WkibuPyDHFWH+i8vBmHknQyV5cg/ZDNpX7vffgsmVC07IVRqKrBRUZJa+GSCxyVdHewYes pmuTrAQ2U4F9lmg== X-Developer-Key: i=tomi.valkeinen@ideasonboard.com; a=openpgp; fpr=C4380C3E965EFD81079FF3A7FA3DAA8CBC961EF5 TC358768 has two ways to send DSI commands: 1) buffer the payload data into registers (DSICMD_WDx), which supports up to 8 bytes of payload, 2) buffer the payload data into the video buffer, which supports up to 1024 bytes of payload. The driver currently supports method 1). Add support for transmitting long DSI commands (more than 8 bytes, up to 1024 bytes) using the video buffer. This mode can only be used before the actual video transmission is enabled, i.e. the initial configuration. Original version from Parth Pancholi Tested-by: Jo=C3=A3o Paulo Gon=C3=A7alves # To= radex Verdin AM62 Reviewed-by: Francesco Dolcini Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 79 ++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc3= 58768.c index e1ed4003b3c5..e0b5a4b5abbe 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -45,6 +45,9 @@ =20 /* Debug (16-bit addressable) */ #define TC358768_VBUFCTRL 0x00E0 +#define TC358768_VBUFCTRL_VBUF_EN BIT(15) +#define TC358768_VBUFCTRL_TX_EN BIT(14) +#define TC358768_VBUFCTRL_MASK BIT(13) #define TC358768_DBG_WIDTH 0x00E2 #define TC358768_DBG_VBLANK 0x00E4 #define TC358768_DBG_DATA 0x00E8 @@ -537,9 +540,21 @@ static ssize_t tc358768_dsi_host_transfer(struct mipi_= dsi_host *host, return -ENOTSUPP; } =20 + if (msg->tx_len > 1024) { + dev_warn(priv->dev, "Maximum 1024 byte MIPI tx is supported\n"); + return -EINVAL; + } + if (msg->tx_len > 8) { - dev_warn(priv->dev, "Maximum 8 byte MIPI tx is supported\n"); - return -ENOTSUPP; + u32 confctl; + + tc358768_read(priv, TC358768_CONFCTL, &confctl); + + if (confctl & BIT(6)) { + dev_warn(priv->dev, + "Video is currently active. Unable to transmit long command\n"); + return -EBUSY; + } } =20 ret =3D mipi_dsi_create_packet(&packet, msg); @@ -552,23 +567,66 @@ static ssize_t tc358768_dsi_host_transfer(struct mipi= _dsi_host *host, tc358768_write(priv, TC358768_DSICMD_WC, 0); tc358768_write(priv, TC358768_DSICMD_WD0, (packet.header[2] << 8) | packet.header[1]); - } else { - int i; - + tc358768_dsicmd_tx(priv); + } else if (packet.payload_length <=3D 8) { tc358768_write(priv, TC358768_DSICMD_TYPE, (0x40 << 8) | (packet.header[0] & 0x3f)); tc358768_write(priv, TC358768_DSICMD_WC, packet.payload_length); - for (i =3D 0; i < packet.payload_length; i +=3D 2) { + + for (int i =3D 0; i < packet.payload_length; i +=3D 2) { u16 val =3D packet.payload[i]; =20 if (i + 1 < packet.payload_length) val |=3D packet.payload[i + 1] << 8; - tc358768_write(priv, TC358768_DSICMD_WD0 + i, val); } - } =20 - tc358768_dsicmd_tx(priv); + tc358768_dsicmd_tx(priv); + } else { + unsigned long tx_sleep_us; + size_t len; + + /* For packets over 8 bytes we need to use the video buffer */ + tc358768_write(priv, TC358768_DATAFMT, BIT(0)); /* txdt_en */ + tc358768_write(priv, TC358768_DSITX_DT, packet.header[0] & 0x3f); + tc358768_write(priv, TC358768_CMDBYTE, packet.payload_length); + tc358768_write(priv, TC358768_VBUFCTRL, TC358768_VBUFCTRL_VBUF_EN); + + /* + * Write the payload in 2-byte chunks, and pad with zeroes to + * align to 4 bytes. + */ + len =3D ALIGN(packet.payload_length, 4); + + for (int i =3D 0; i < len; i +=3D 2) { + u16 val =3D 0; + + if (i < packet.payload_length) + val |=3D packet.payload[i]; + if (i + 1 < packet.payload_length) + val |=3D packet.payload[i + 1] << 8; + + tc358768_write(priv, TC358768_DBG_DATA, val); + } + + /* Start transmission */ + tc358768_write(priv, TC358768_VBUFCTRL, + TC358768_VBUFCTRL_VBUF_EN | + TC358768_VBUFCTRL_TX_EN | + TC358768_VBUFCTRL_MASK); + + /* + * The TC358768 spec says to wait until the transmission has + * been finished, estimating the sleep time based on the payload + * and clock rates. We use a simple safe estimate of 2us per + * byte (LP mode transmission). + */ + tx_sleep_us =3D packet.payload_length * 2; + usleep_range(tx_sleep_us, tx_sleep_us * 2); + + tc358768_write(priv, TC358768_VBUFCTRL, TC358768_VBUFCTRL_MASK); + tc358768_write(priv, TC358768_VBUFCTRL, 0); /* Stop transmission */ + } =20 ret =3D tc358768_clear_error(priv); if (ret) @@ -752,6 +810,9 @@ static void tc358768_bridge_atomic_pre_enable(struct dr= m_bridge *bridge, return; } =20 + /* Release RstPtr so that the video buffer can be used for DSI commands */ + tc358768_update_bits(priv, TC358768_PP_MISC, BIT(14), 0); + connector =3D drm_atomic_get_new_connector_for_encoder(state, bridge->enc= oder); conn_state =3D drm_atomic_get_new_connector_state(state, connector); crtc_state =3D drm_atomic_get_new_crtc_state(state, conn_state->crtc); --=20 2.43.0