[PATCH v3 1/2] drm/bridge: Add Cadence DSI driver
Tomi Valkeinen
tomi.valkeinen at ti.com
Wed Sep 20 11:55:02 UTC 2017
Hi Boris,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 31/08/17 18:55, Boris Brezillon wrote:
> Add a driver for Cadence DPI -> DSI bridge.
>
> This driver only support a subset of Cadence DSI bridge capabilities.
>
> Here is a non-exhaustive list of missing features:
> * burst mode
> * dynamic configuration of the DPHY based on the
> * support for additional input interfaces (SDI input)
>
> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> ---
> Changes in v3:
> - replace magic values by real timing calculation. The DPHY PLL clock
> is still hardcoded since we don't have a working DPHY block yet, and
> this is the piece of HW we need to dynamically configure the PLL
> rate based on the display refresh rate and the resolution.
> - parse DSI devices represented with the OF-graph. This is needed to
> support DSI devices controlled through an external bus like I2C or
> SPI.
> - use the DRM panel-bridge infrastructure to simplify the DRM panel
> logic
>
> Changes in v2:
> - rebase on v4.12-rc1 and adapt to driver to the drm_bridge API changes
> - return the correct error when devm_clk_get(sysclk) fails
> - add missing depends on OF and select DRM_PANEL in the Kconfig entry
> ---
> drivers/gpu/drm/bridge/Kconfig | 9 +
> drivers/gpu/drm/bridge/Makefile | 1 +
> drivers/gpu/drm/bridge/cdns-dsi.c | 1090 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 1100 insertions(+)
> create mode 100644 drivers/gpu/drm/bridge/cdns-dsi.c
We need some power management. At the moment the clocks are kept always
enabled. Those need to be turned off when the IP is not used.
> +static irqreturn_t cdns_dsi_interrupt(int irq, void *data)
> +{
> + struct cdns_dsi *dsi = data;
> + irqreturn_t ret = IRQ_NONE;
> + u32 flag, ctl;
> +
> + flag = readl(dsi->regs + DIRECT_CMD_STS_FLAG);
> + if (flag) {
> + ctl = readl(dsi->regs + DIRECT_CMD_STS_CTL);
> + ctl &= ~flag;
> + writel(ctl, dsi->regs + DIRECT_CMD_STS_CTL);
I presume it's the enable/disable bit in STS_CTL that prevents the
interrupt from triggering again, instead of the status flag? Just making
sure, because I think on some IPs the status flag has been the one that
triggers the interrupt.
> + complete(&dsi->direct_cmd_comp);
> + ret = IRQ_HANDLED;
> + }
> +
> + return ret;
> +}
> +
> +static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
> + const struct mipi_dsi_msg *msg)
> +{
> + struct cdns_dsi *dsi = to_cdns_dsi(host);
> + u32 cmd, sts, val, wait = WRITE_COMPLETED, ctl = 0;
> + struct mipi_dsi_packet packet;
> + int ret, i, tx_len, rx_len;
> +
> + ret = mipi_dsi_create_packet(&packet, msg);
> + if (ret)
> + return ret;
> +
> + tx_len = msg->tx_buf ? msg->tx_len : 0;
> + rx_len = msg->rx_buf ? msg->rx_len : 0;
> +
> + /* For read operations, the maximum TX len is 2. */
Hmm, why is that?
> + if (rx_len && tx_len > 2)
> + return -ENOTSUPP;
> +
> + /* TX len is limited by the CMD FIFO depth. */
> + if (tx_len > dsi->direct_cmd_fifo_depth)
> + return -ENOTSUPP;
> +
> + /* RX len is limited by the RX FIFO depth. */
> + if (rx_len > dsi->rx_fifo_depth)
> + return -ENOTSUPP;
> +
> + cmd = CMD_SIZE(tx_len) | CMD_VCHAN_ID(msg->channel) |
> + CMD_DATATYPE(msg->type);
> +
> + if (msg->flags & MIPI_DSI_MSG_USE_LPM)
> + cmd |= CMD_LP_EN;
> +
> + if (mipi_dsi_packet_format_is_long(msg->type))
> + cmd |= CMD_LONG;
> +
> + if (rx_len) {
> + cmd |= READ_CMD;
> + wait = READ_COMPLETED_WITH_ERR | READ_COMPLETED;
> + ctl = READ_EN | BTA_EN;
> + } else if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
> + cmd |= BTA_REQ;
> + wait = ACK_WITH_ERR_RCVD | ACK_RCVD;
> + ctl = BTA_EN;
> + }
It's been a while since I worked with DSI, but... Shouldn't there be a
check somewhere that the packet(s) can fit into the blanking intervals?
Tomi
More information about the dri-devel
mailing list