Re: [PATCH v2 10/23] drm/msm/dcp: Add HFI DSI and panel commands

From: Dmitry Baryshkov

Date: Tue Oct 27 2026 - 07:08:00 EST


On Mon, Oct 26, 2026 at 11:51:20AM +0530, Jayant Shekhar wrote:
> Translate DSI host and panel operations into HFI commands. Firmware
> owns the DSI hardware, so mode validation, display power, panel setup,
> and DCS transfers must cross the HFI interface instead of accessing
> controller registers from Linux.
>
> Implement DSI mode validation, display session and power management,
> panel initialization, and DCS transfer helpers while keeping them
> separate from generic display commands.
>
> Assisted-by: LLM
> Signed-off-by: Jayant Shekhar <jayant.shekhar@xxxxxxxxxxxxxxxx>
> ---
> drivers/gpu/drm/msm/Makefile | 2 +
> drivers/gpu/drm/msm/dcp/dcp_dsi_panel.h | 81 ++++
> drivers/gpu/drm/msm/dcp/dcp_hfi.h | 25 ++
> drivers/gpu/drm/msm/dcp/dcp_hfi_dsi.c | 252 ++++++++++++
> drivers/gpu/drm/msm/dcp/dcp_hfi_dsi_panel.c | 592 ++++++++++++++++++++++++++++

Please stop calling it a panel. There can be any bridge after the DSI
device. From the Linux point of view, drm_panel is a subclass of
drm_bridge.

> 5 files changed, 952 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index bdc5e3b8efa7..77c268aabca6 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -74,6 +74,8 @@ msm-display-$(CONFIG_DRM_MSM_MDP5) += \
> msm-display-$(CONFIG_DRM_MSM_DCP) += \
> dcp/dcp_hfi_core.o \
> dcp/dcp_hfi_crtc.o \
> + dcp/dcp_hfi_dsi.o \
> + dcp/dcp_hfi_dsi_panel.o \
> dcp/dcp_hfi_encoder.o \
> dcp/dcp_hfi_kms.o \
> dcp/dcp_hfi_plane.o \
> diff --git a/drivers/gpu/drm/msm/dcp/dcp_dsi_panel.h b/drivers/gpu/drm/msm/dcp/dcp_dsi_panel.h
> new file mode 100644
> index 000000000000..a8898e469b44
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/dcp/dcp_dsi_panel.h
> @@ -0,0 +1,81 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * DCP DSI panel configuration shared by the HFI panel implementation and

What if there is a DSI2DPI or DSI2LVDS bridge and then DPI or LVDS
panel?

> + * the DRM DSI bridge.
> + */
> +
> +#ifndef __DCP_DSI_PANEL_H__
> +#define __DCP_DSI_PANEL_H__
> +
> +#include <linux/dma-mapping.h>
> +#include <linux/sizes.h>
> +#include <linux/types.h>
> +
> +#define DCP_DSI_MAX_PHY_TIMINGS 32
> +
> +/**
> + * struct dcp_dsi_hfi_panel_config - Complete HFI PANEL_INIT configuration.
> + *
> + * This contains the bridge-owned panel configuration plus the
> + * mode-dependent values assembled before the HFI PANEL_INIT command.
> + */
> +struct dcp_dsi_hfi_panel_config {
> + u32 display_type;
> + u32 num_ctrls;
> + u32 ctrl_indices[4];
> + u32 num_phys;
> + u32 phy_indices[4];
> + u32 vsync_source;
> + u32 te_dcs_command;
> + u32 dma_trigger;
> + u32 stream_trigger;
> + u32 wr_mem_start;
> + u32 wr_mem_continue;
> + u32 dma_sched_line;
> + u32 dma_sched_window;
> + u32 phy_type;
> + bool cphy_mode;
> + bool lp11_init;
> + bool ulps_supported;
> + bool bllp_eof_power_mode;
> + bool bllp_power_mode;
> + u32 lane_map;
> + u32 color_order;
> + u32 esd_mode;
> + u32 jitter_numer;
> + u32 jitter_denom;
> + dma_addr_t dcs_tx_dva;
> + dma_addr_t dcs_tx_iova;
> + u32 dcs_tx_buf_size;
> + u32 phy_timings[DCP_DSI_MAX_PHY_TIMINGS];
> + u32 num_phy_timings;
> + bool dsc_enabled;
> + u32 dsc_version_major;
> + u32 dsc_version_minor;
> + u32 dsc_scr_version;
> + u32 dsc_slice_height;
> + u32 dsc_slice_width;
> + u32 dsc_slices_per_pkt;
> + u32 dsc_bits_per_component;
> + u32 dsc_pps_delay_ms;
> + u32 dsc_bits_per_pixel;
> + u32 dsc_chroma_format;
> + u32 dsc_color_space;
> + u32 dsc_block_prediction_enable;

Why do you need to copy those? Can't you use struct drm_dsc directly?
Having it as a non-NULL pointer would have saved you from having
the dsc_enabled flag.

> + /* Optional DSC rate-control override panel configuration. */
> + bool dsc_rc_override;
> + u8 dsc_rc_min_qp[15];
> + u8 dsc_rc_max_qp[15];
> + u8 dsc_rc_bpg_offsets[15];
> + u32 topology_mixer_count;
> + u32 topology_enc_count;
> + u32 topology_intf_count;
> +};
> +
> +/* DCS buffers use IOVAs directly in the firmware command descriptor. */
> +#define DCP_DSI_DCS_TX_BUF_SIZE SZ_4K
> +#define DCP_DSI_DCS_RX_BUF_SIZE SZ_4K
> +
> +#endif /* __DCP_DSI_PANEL_H__ */
> diff --git a/drivers/gpu/drm/msm/dcp/dcp_hfi.h b/drivers/gpu/drm/msm/dcp/dcp_hfi.h
> index 6d3eadb5e811..88d73de69383 100644
> --- a/drivers/gpu/drm/msm/dcp/dcp_hfi.h
> +++ b/drivers/gpu/drm/msm/dcp/dcp_hfi.h
> @@ -242,6 +242,31 @@ int dcp_hfi_send_resource_register(struct dcp_hfi *hfi);
> int dcp_hfi_set_display_property(struct dcp_hfi *hfi, u32 session_id,
> u32 prop_id, u32 value);
>
> +struct dcp_dsi_hfi_panel_config;
> +int dcp_hfi_panel_init(struct dcp_hfi *hfi, u32 intf_idx,
> + const struct drm_display_mode *mode,
> + const struct mipi_dsi_device *dsi,
> + const struct dcp_dsi_hfi_panel_config *cfg);
> +int dcp_hfi_display_enable(struct dcp_hfi *hfi, u32 intf_idx,
> + u32 display_id, u32 *session_id);
> +int dcp_hfi_display_close(struct dcp_hfi *hfi, u32 session_id);
> +int dcp_hfi_display_mode_validate(struct dcp_hfi *hfi, u32 session_id,
> + const struct drm_display_mode *mode,
> + u64 clk_rate_hz);
> +int dcp_hfi_display_set_mode(struct dcp_hfi *hfi, u32 session_id,
> + const struct drm_display_mode *mode,
> + u64 clk_rate_hz);
> +int dcp_hfi_display_power_register(struct dcp_hfi *hfi, u32 session_id);
> +int dcp_hfi_display_power_control_ack(struct dcp_hfi *hfi, u32 session_id,
> + u32 packet_id);
> +int dcp_hfi_display_post_enable(struct dcp_hfi *hfi, u32 session_id);
> +int dcp_hfi_display_disable(struct dcp_hfi *hfi, u32 session_id);
> +int dcp_hfi_display_post_disable(struct dcp_hfi *hfi, u32 session_id);
> +ssize_t dcp_hfi_dcs_transfer(struct dcp_hfi *hfi, u32 session_id,
> + const struct mipi_dsi_msg *msg,
> + void *tx_buf, dma_addr_t tx_iova,
> + void *rx_buf, dma_addr_t rx_iova,
> + u32 post_wait_ms, u32 ctrl_idx);
> #endif /* __DCP_HFI_H__ */
> void dcp_hfi_set_power_control_cb(struct dcp_hfi *hfi, void *priv,
> void (*cb)(void *priv, u32 display_id,
> diff --git a/drivers/gpu/drm/msm/dcp/dcp_hfi_dsi.c b/drivers/gpu/drm/msm/dcp/dcp_hfi_dsi.c
> new file mode 100644
> index 000000000000..fbeec03cf90d
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/dcp/dcp_hfi_dsi.c
> @@ -0,0 +1,252 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * HFI commands for the DSI display-session lifecycle.
> + * Panel initialization and DCS transfers are implemented in dcp_hfi_dsi_panel.c.
> + */
> +
> +#include <linux/device.h>
> +#include <drm/drm_modes.h>
> +
> +#include "dcp_hfi.h"
> +#include "dcp_hfi_priv.h"
> +#include "hfi/hfi_commands_display.h"
> +#include "hfi/hfi_defs_common.h"
> +#include "hfi/hfi_defs_display.h"
> +#include "hfi/hfi_packet.h"
> +#include "hfi/hfi_packer.h"
> +#include "hfi/hfi_properties_display.h"
> +
> +static void dcp_hfi_fill_mode_info(struct hfi_display_mode_info *info,
> + const struct drm_display_mode *mode)
> +{
> + memset(info, 0, sizeof(*info));
> + info->size = sizeof(*info);
> + info->h_active = mode->hdisplay;
> + info->h_back_porch = mode->htotal - mode->hsync_end;
> + info->h_sync_width = mode->hsync_end - mode->hsync_start;
> + info->h_front_porch = mode->hsync_start - mode->hdisplay;
> + info->h_skew = mode->hskew;
> + info->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC);
> + info->v_active = mode->vdisplay;
> + info->v_back_porch = mode->vtotal - mode->vsync_end;
> + info->v_sync_width = mode->vsync_end - mode->vsync_start;
> + info->v_front_porch = mode->vsync_start - mode->vdisplay;
> + info->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC);
> + info->refresh_rate = drm_mode_vrefresh(mode);
> + info->clk_rate_hz_lo = lower_32_bits((u64)mode->clock * 1000);
> + info->clk_rate_hz_hi = upper_32_bits((u64)mode->clock * 1000);
> +}
> +
> +static void dcp_hfi_dump_mode_info(struct dcp_hfi *hfi, const char *cmd,
> + u32 session_id,
> + const struct hfi_display_mode_info *info)
> +{
> + dev_dbg(hfi->dev,
> + "HFI %s s=%u h=%u/%u/%u/%u v=%u/%u/%u/%u p=%u/%u r=%u clk=%llu sz=%u\n",
> + cmd, session_id,
> + info->h_active, info->h_back_porch, info->h_sync_width,
> + info->h_front_porch,
> + info->v_active, info->v_back_porch, info->v_sync_width,
> + info->v_front_porch,
> + info->h_sync_polarity, info->v_sync_polarity,
> + info->refresh_rate,
> + (u64)info->clk_rate_hz_lo | ((u64)info->clk_rate_hz_hi << 32),
> + info->size);
> +}
> +
> +int dcp_hfi_display_mode_validate(struct dcp_hfi *hfi, u32 session_id,
> + const struct drm_display_mode *mode, u64 clk_rate_hz)
> +{
> + struct hfi_display_mode_info info;
> + int ret;
> +
> + dcp_hfi_fill_mode_info(&info, mode);
> + info.clk_rate_hz_lo = lower_32_bits(clk_rate_hz);
> + info.clk_rate_hz_hi = upper_32_bits(clk_rate_hz);
> + dcp_hfi_dump_mode_info(hfi, "HFI MODE_VALIDATE", session_id, &info);
> +
> + ret = dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_MODE_VALIDATE,
> + HFI_CMD_BUFF_DISPLAY, session_id,
> + HFI_PAYLOAD_U32_ARRAY,
> + &info, sizeof(info),
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_MODE_MS);
> +
> + return ret;
> +}
> +
> +int dcp_hfi_display_set_mode(struct dcp_hfi *hfi, u32 session_id,
> + const struct drm_display_mode *mode, u64 clk_rate_hz)
> +{
> + struct hfi_display_mode_info info;
> + int ret;
> +
> + dcp_hfi_fill_mode_info(&info, mode);
> + info.clk_rate_hz_lo = lower_32_bits(clk_rate_hz);
> + info.clk_rate_hz_hi = upper_32_bits(clk_rate_hz);
> + dcp_hfi_dump_mode_info(hfi, "HFI SET_MODE", session_id, &info);
> +
> + ret = dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_SET_MODE,
> + HFI_CMD_BUFF_DISPLAY, session_id,
> + HFI_PAYLOAD_U32_ARRAY,
> + &info, sizeof(info),
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_MODE_MS);
> +
> + return ret;
> +}
> +
> +int dcp_hfi_display_power_register(struct dcp_hfi *hfi, u32 session_id)
> +{
> + return dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_POWER_REGISTER,
> + HFI_CMD_BUFF_DISPLAY, session_id,
> + HFI_PAYLOAD_NONE, NULL, 0,
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_DISPLAY_MS);
> +}
> +
> +int dcp_hfi_display_power_control_ack(struct dcp_hfi *hfi, u32 session_id,
> + u32 packet_id)
> +{
> + struct dcp_hfi_buf *buf;
> + struct hfi_cmd_buff_hdl hdl;
> + struct hfi_header_info hdr_info;
> + struct hfi_packet_info pkt_info;
> + int ret;
> +
> + buf = dcp_hfi_buf_alloc(hfi);
> + if (!buf)
> + return -ENOMEM;
> +
> + hdl.cmd_buffer = buf->data;
> + hdl.size = DCP_HFI_BUF_SIZE;
> +
> + hdr_info.num_packets = 0;
> + hdr_info.cmd_buff_type = HFI_CMD_BUFF_DISPLAY;
> + hdr_info.object_id = session_id;
> + hdr_info.header_id = dcp_hfi_next_packet_id(hfi);
> +
> + ret = hfi_create_header(&hdl, &hdr_info);
> + if (ret)
> + goto err_free_buf;
> +
> + pkt_info.cmd = HFI_COMMAND_DISPLAY_POWER_CONTROL;
> + pkt_info.id = session_id & 0xFFFF;
> + pkt_info.flags = HFI_RX_FLAGS_SUCCESS;
> + pkt_info.packet_id = packet_id;
> + pkt_info.payload_type = HFI_PAYLOAD_NONE;
> + pkt_info.payload_size = 0;
> + pkt_info.payload_ptr = NULL;
> +
> + ret = hfi_create_packet_header(&hdl, &pkt_info);
> + if (ret)
> + goto err_free_buf;
> +
> + return dcp_hfi_send_cmd_async(hfi, buf, hfi_get_header_size(&hdl), NULL);
> +
> +err_free_buf:
> + dcp_hfi_buf_free(hfi, buf);
> + return ret;
> +}
> +
> +int dcp_hfi_display_enable(struct dcp_hfi *hfi, u32 intf_idx, u32 display_id,
> + u32 *session_id)
> +{
> + int ret;
> +
> + ret = dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_ENABLE,
> + HFI_CMD_BUFF_DISPLAY, display_id,
> + HFI_PAYLOAD_NONE, NULL, 0,
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_DISPLAY_MS);
> + if (ret) {
> + dev_err(hfi->dev,
> + "HFI DISPLAY_ENABLE intf=%u display_id=%u failed: %d\n",
> + intf_idx, display_id, ret);
> + return ret;
> + }
> +
> + *session_id = display_id;
> +
> + return 0;
> +}
> +
> +int dcp_hfi_display_post_enable(struct dcp_hfi *hfi, u32 session_id)
> +{
> + return dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_POST_ENABLE,
> + HFI_CMD_BUFF_DISPLAY, session_id,
> + HFI_PAYLOAD_NONE, NULL, 0,
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_DISPLAY_MS);
> +}
> +
> +int dcp_hfi_display_disable(struct dcp_hfi *hfi, u32 session_id)
> +{
> + return dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_DISABLE,
> + HFI_CMD_BUFF_DISPLAY, session_id,
> + HFI_PAYLOAD_NONE, NULL, 0,
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_DISPLAY_MS);
> +}
> +
> +int dcp_hfi_display_post_disable(struct dcp_hfi *hfi, u32 session_id)
> +{
> + return dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_POST_DISABLE,
> + HFI_CMD_BUFF_DISPLAY, session_id,
> + HFI_PAYLOAD_NONE, NULL, 0,
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_DISPLAY_MS);
> +}
> +
> +int dcp_hfi_display_close(struct dcp_hfi *hfi, u32 session_id)
> +{
> + int ret;
> +
> + ret = dcp_hfi_display_disable(hfi, session_id);
> + if (ret) {
> + dev_warn(hfi->dev, "HFI DISPLAY_DISABLE failed: %d\n", ret);
> + return ret;
> + }
> +
> + ret = dcp_hfi_display_post_disable(hfi, session_id);
> + if (ret) {
> + dev_warn(hfi->dev, "HFI DISPLAY_POST_DISABLE failed: %d\n", ret);
> + return ret;
> + }

Why are there two types of calls, pre and post? Should they go to the
corresponding separate DRM callbacks?

> +
> + ret = dcp_hfi_send_sync(hfi,
> + HFI_COMMAND_DISPLAY_CLOSE,
> + HFI_CMD_BUFF_DISPLAY, session_id,
> + HFI_PAYLOAD_NONE, NULL, 0,
> + HFI_TX_FLAGS_RESPONSE_REQUIRED |
> + HFI_TX_FLAGS_NON_DISCARDABLE,
> + NULL, 0,
> + DCP_HFI_TIMEOUT_DISPLAY_MS);
> + if (ret)
> + dev_warn(hfi->dev, "HFI DISPLAY_CLOSE failed: %d\n", ret);
> +
> + return ret;
> +}
> diff --git a/drivers/gpu/drm/msm/dcp/dcp_hfi_dsi_panel.c b/drivers/gpu/drm/msm/dcp/dcp_hfi_dsi_panel.c
> new file mode 100644
> index 000000000000..b27fa8fa3160
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/dcp/dcp_hfi_dsi_panel.c
> @@ -0,0 +1,592 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * HFI commands for panel initialization and DCS transfers.
> + * Firmware owns the DSI controller and PHY.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/math64.h>
> +#include <drm/drm_modes.h>
> +#include <drm/drm_mipi_dsi.h>
> +
> +#include "dcp_dsi_panel.h"
> +#include "dcp_hfi.h"
> +#include "dcp_hfi_priv.h"
> +#include "hfi/hfi_commands_display.h"
> +#include "hfi/hfi_commands_panel.h"
> +#include "hfi/hfi_defs_common.h"
> +#include "hfi/hfi_defs_panel.h"
> +#include "hfi/hfi_packet.h"
> +#include "hfi/hfi_packer.h"
> +#include "hfi/hfi_properties_panel.h"
> +
> +#define DCP_DSI_CTRL_CMD_READ BIT(0)
> +#define DCP_DSI_CTRL_CMD_FETCH_MEMORY BIT(5)
> +#define DCP_DSI_CTRL_CMD_LAST_COMMAND BIT(6)
> +
> +static u32 dcp_bpp_to_hfi(u32 bpp)
> +{
> + switch (bpp) {
> + case 16: return HFI_PANEL_BPP_16;
> + case 18: return HFI_PANEL_BPP_18;
> + case 30: return HFI_PANEL_BPP_30;
> + case 24:
> + default: return HFI_PANEL_BPP_24;
> + }
> +}
> +
> +static u32 dcp_dsi_traffic_mode(const struct mipi_dsi_device *dsi)
> +{
> + if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO))
> + return HFI_PANEL_TRAFFIC_NON_BURST_SYNC_EVENT_MODE;
> + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
> + return HFI_PANEL_TRAFFIC_BURST_MODE;
> + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
> + return HFI_PANEL_TRAFFIC_NON_BURST_SYNC_PULSE_MODE;
> + return HFI_PANEL_TRAFFIC_NON_BURST_SYNC_EVENT_MODE;
> +}
> +
> +static u32 dcp_lanes_to_hfi(u32 num_lanes)
> +{
> + u32 mask = 0;
> +
> + if (num_lanes >= 1)
> + mask |= HFI_PANEL_LANE_0;

There is always at least one lane. Set the mask to HFI_PANEL_LANE_0.

> + if (num_lanes >= 2)
> + mask |= HFI_PANEL_LANE_1;
> + if (num_lanes >= 3)
> + mask |= HFI_PANEL_LANE_2;
> + if (num_lanes >= 4)
> + mask |= HFI_PANEL_LANE_3;
> +
> + return mask ?: HFI_PANEL_LANE_0;
> +}
> +
> +static bool dcp_hfi_panel_wait(struct dcp_hfi *hfi,
> + struct dcp_hfi_completion *comp)
> +{
> + unsigned long flags;
> +
> + if (wait_for_completion_timeout(&comp->done,
> + msecs_to_jiffies(DCP_HFI_TIMEOUT_DISPLAY_MS)))
> + return false;
> +
> + /* Serialize removal with response dispatch before the stack object dies. */
> + spin_lock_irqsave(&hfi->resp_drain_lock, flags);
> + dcp_hfi_pending_find(hfi, comp->packet_id);
> + spin_unlock_irqrestore(&hfi->resp_drain_lock, flags);
> + return true;
> +}
> +
> +int dcp_hfi_panel_init(struct dcp_hfi *hfi, u32 intf_idx,
> + const struct drm_display_mode *mode,
> + const struct mipi_dsi_device *dsi,
> + const struct dcp_dsi_hfi_panel_config *cfg)
> +{
> + u32 num_lanes;
> + u32 bpp;
> + bool is_cmd_mode;
> + u32 display_type;
> + u32 vsync_source;
> + u32 traffic_mode;
> + u32 phy_type;
> +
> + struct dcp_hfi_buf *buf1, *buf2;
> + struct hfi_cmd_buff_hdl hdl1, hdl2;
> + struct hfi_header_info hdr_info1, hdr_info2;
> + struct hfi_packet_info pkt_info;
> + struct dcp_hfi_completion comp1, comp2, comp3;
> + u32 payload[128];
> + u32 *p;
> + u32 packet_id, packet_id2, packet_id3;
> + u64 clk_hz;
> + int ret;
> + bool timeout1, timeout2, timeout3;
> + u32 link_bpp_x16;

Reverse christmas tree, apply universally to all your code.

> +
> + if (!hfi || !mode || !dsi || !dsi->lanes || !cfg)
> + return -EINVAL;

And which of those can actually be passed as NULL?

> + if (cfg->num_ctrls > ARRAY_SIZE(cfg->ctrl_indices) ||
> + cfg->num_phys > ARRAY_SIZE(cfg->phy_indices))
> + return -EINVAL;
> +
> + display_type = cfg->display_type;
> + vsync_source = cfg->vsync_source;
> + phy_type = cfg->phy_type;
> + num_lanes = dsi->lanes;
> + bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> + if (bpp < 0)
> + return -EINVAL;
> + is_cmd_mode = !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
> + traffic_mode = dcp_dsi_traffic_mode(dsi);
> + link_bpp_x16 = bpp << 4;
> +
> + buf1 = dcp_hfi_buf_alloc(hfi);
> + if (!buf1) {
> + dev_err(hfi->dev, "HFI PANEL_INIT: TX buffer exhausted\n");
> + return -ENOMEM;
> + }
> +
> + hdl1.cmd_buffer = buf1->data;
> + hdl1.size = DCP_HFI_BUF_SIZE;
> +
> + hdr_info1.num_packets = 0;
> + hdr_info1.cmd_buff_type = HFI_CMD_BUFF_DISPLAY;
> + hdr_info1.object_id = intf_idx;
> + hdr_info1.header_id = dcp_hfi_next_packet_id(hfi);
> +
> + ret = hfi_create_header(&hdl1, &hdr_info1);
> + if (ret) {
> + dev_err(hfi->dev, "PANEL_INIT: hfi_create_header (A) failed: %d\n",
> + ret);
> + goto err_free_buf1;
> + }
> +
> + {

Jayant, you really like to ignore comments. Please stop doing that. And
also please stop having unconditional nested blocks. If you need one,
extract it to a function.

> + u32 num_props = 0;
> +
> + p = payload + 1;
> + num_props++;
> + p += HFI_PACK(p, HFI_PROPERTY_PANEL_TIMING_MODE_COUNT, 1);
> +
> + /* DCS TX buffer is described by both DVA and IOVA properties. */
> + if (cfg->dcs_tx_iova && cfg->dcs_tx_dva &&
> + !(cfg->dcs_tx_iova & 0x3ff) && !(cfg->dcs_tx_dva & 0x3ff)) {
> + num_props++;
> + p += HFI_PACK(p, HFI_PROPERTY_PANEL_DCS_CMD_TX_BUF_DVA,
> + lower_32_bits(cfg->dcs_tx_dva),
> + upper_32_bits(cfg->dcs_tx_dva),
> + cfg->dcs_tx_buf_size, 0, 0);
> + num_props++;
> + p += HFI_PACK(p, HFI_PROPERTY_PANEL_DCS_CMD_TX_BUF_IOVA,
> + lower_32_bits(cfg->dcs_tx_iova),
> + upper_32_bits(cfg->dcs_tx_iova),
> + cfg->dcs_tx_buf_size, 0, 0);
> + }
> + payload[0] = num_props;
> + }
> +

--
With best wishes
Dmitry