Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8264f12b authored by Tharun Raj Soma's avatar Tharun Raj Soma Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm: add split link panel support in sde drm



In split link panels, the four data lanes are split into
sublinks and the clock lane is shared among these sublinks.
This change adds support for split link panels in sde drm.

Change-Id: I583e255bc94aef1fb3050e7d75934534ab772cb3
Signed-off-by: default avatarTharun Raj Soma <tsoma@codeaurora.org>
parent 3427fa9a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -5479,6 +5479,7 @@ int dsi_display_get_info(struct drm_connector *connector,
{
	struct dsi_display *display;
	struct dsi_panel_phy_props phy_props;
	struct dsi_host_common_cfg *host;
	int i, rc;

	if (!info || !disp) {
@@ -5540,6 +5541,10 @@ int dsi_display_get_info(struct drm_connector *connector,

	info->te_source = display->te_source;

	host = &display->panel->host_config;
	if (host->split_link.split_link_enabled)
		info->capabilities |= MSM_DISPLAY_SPLIT_LINK;

error:
	mutex_unlock(&display->display_lock);
	return rc;
+2 −0
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ enum msm_display_compression_ratio {
 * @MSM_DISPLAY_CAP_EDID:               EDID supported
 * @MSM_DISPLAY_ESD_ENABLED:            ESD feature enabled
 * @MSM_DISPLAY_CAP_MST_MODE:           Display with MST support
 * @MSM_DISPLAY_SPLIT_LINK:             Split Link enabled
 */
enum msm_display_caps {
	MSM_DISPLAY_CAP_VID_MODE	= BIT(0),
@@ -245,6 +246,7 @@ enum msm_display_caps {
	MSM_DISPLAY_CAP_EDID		= BIT(3),
	MSM_DISPLAY_ESD_ENABLED		= BIT(4),
	MSM_DISPLAY_CAP_MST_MODE	= BIT(5),
	MSM_DISPLAY_SPLIT_LINK		= BIT(6),
};

/**
+20 −15
Original line number Diff line number Diff line
@@ -837,7 +837,7 @@ void sde_encoder_helper_split_config(
		enum sde_intf interface)
{
	struct sde_encoder_virt *sde_enc;
	struct split_pipe_cfg cfg = { 0 };
	struct split_pipe_cfg *cfg;
	struct sde_hw_mdp *hw_mdptop;
	enum sde_rm_topology_name topology;
	struct msm_display_info *disp_info;
@@ -850,10 +850,15 @@ void sde_encoder_helper_split_config(
	sde_enc = to_sde_encoder_virt(phys_enc->parent);
	hw_mdptop = phys_enc->hw_mdptop;
	disp_info = &sde_enc->disp_info;
	cfg = &phys_enc->hw_intf->cfg;
	memset(cfg, 0, sizeof(*cfg));

	if (disp_info->intf_type != DRM_MODE_CONNECTOR_DSI)
		return;

	if (disp_info->capabilities & MSM_DISPLAY_SPLIT_LINK)
		cfg->split_link_en = true;

	/**
	 * disable split modes since encoder will be operating in as the only
	 * encoder, either for the entire use case in the case of, for example,
@@ -862,43 +867,43 @@ void sde_encoder_helper_split_config(
	 */
	if (phys_enc->split_role == ENC_ROLE_SOLO) {
		if (hw_mdptop->ops.setup_split_pipe)
			hw_mdptop->ops.setup_split_pipe(hw_mdptop, &cfg);
			hw_mdptop->ops.setup_split_pipe(hw_mdptop, cfg);
		if (hw_mdptop->ops.setup_pp_split)
			hw_mdptop->ops.setup_pp_split(hw_mdptop, &cfg);
			hw_mdptop->ops.setup_pp_split(hw_mdptop, cfg);
		return;
	}

	cfg.en = true;
	cfg.mode = phys_enc->intf_mode;
	cfg.intf = interface;
	cfg->en = true;
	cfg->mode = phys_enc->intf_mode;
	cfg->intf = interface;

	if (cfg.en && phys_enc->ops.needs_single_flush &&
	if (cfg->en && phys_enc->ops.needs_single_flush &&
			phys_enc->ops.needs_single_flush(phys_enc))
		cfg.split_flush_en = true;
		cfg->split_flush_en = true;

	topology = sde_connector_get_topology_name(phys_enc->connector);
	if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
		cfg.pp_split_slave = cfg.intf;
		cfg->pp_split_slave = cfg->intf;
	else
		cfg.pp_split_slave = INTF_MAX;
		cfg->pp_split_slave = INTF_MAX;

	if (phys_enc->split_role == ENC_ROLE_MASTER) {
		SDE_DEBUG_ENC(sde_enc, "enable %d\n", cfg.en);
		SDE_DEBUG_ENC(sde_enc, "enable %d\n", cfg->en);

		if (hw_mdptop->ops.setup_split_pipe)
			hw_mdptop->ops.setup_split_pipe(hw_mdptop, &cfg);
			hw_mdptop->ops.setup_split_pipe(hw_mdptop, cfg);
	} else if (sde_enc->hw_pp[0]) {
		/*
		 * slave encoder
		 * - determine split index from master index,
		 *   assume master is first pp
		 */
		cfg.pp_split_index = sde_enc->hw_pp[0]->idx - PINGPONG_0;
		cfg->pp_split_index = sde_enc->hw_pp[0]->idx - PINGPONG_0;
		SDE_DEBUG_ENC(sde_enc, "master using pp%d\n",
				cfg.pp_split_index);
				cfg->pp_split_index);

		if (hw_mdptop->ops.setup_pp_split)
			hw_mdptop->ops.setup_pp_split(hw_mdptop, &cfg);
			hw_mdptop->ops.setup_pp_split(hw_mdptop, cfg);
	}
}

+5 −2
Original line number Diff line number Diff line
@@ -470,8 +470,10 @@ static void sde_encoder_phys_vid_setup_timing_engine(
	u32 qsync_min_fps = 0;
	unsigned long lock_flags;
	struct sde_hw_intf_cfg intf_cfg = { 0 };
	bool is_split_link = false;

	if (!phys_enc || !phys_enc->sde_kms || !phys_enc->hw_ctl) {
	if (!phys_enc || !phys_enc->sde_kms || !phys_enc->hw_ctl ||
					!phys_enc->hw_intf) {
		SDE_ERROR("invalid encoder %d\n", phys_enc != 0);
		return;
	}
@@ -486,7 +488,8 @@ static void sde_encoder_phys_vid_setup_timing_engine(
	SDE_DEBUG_VIDENC(vid_enc, "enabling mode:\n");
	drm_mode_debug_printmodeline(&mode);

	if (phys_enc->split_role != ENC_ROLE_SOLO) {
	is_split_link = phys_enc->hw_intf->cfg.split_link_en;
	if (phys_enc->split_role != ENC_ROLE_SOLO || is_split_link) {
		mode.hdisplay >>= 1;
		mode.htotal >>= 1;
		mode.hsync_start >>= 1;
+7 −1
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
#include "sde_hw_catalog.h"
#include "sde_hw_intf.h"
#include "sde_dbg.h"
#include "sde_kms.h"

#define INTF_TIMING_ENGINE_EN           0x000
#define INTF_CONFIG                     0x004
@@ -52,6 +51,7 @@
#define   INTF_DEFLICKER_STRNG_COEFF    0x0F4
#define   INTF_DEFLICKER_WEAK_COEFF     0x0F8

#define   INTF_REG_SPLIT_LINK           0x080
#define   INTF_DSI_CMD_MODE_TRIGGER_EN  0x084
#define   INTF_PANEL_FORMAT             0x090
#define   INTF_TPG_ENABLE               0x100
@@ -301,6 +301,9 @@ static void sde_hw_intf_setup_timing_engine(struct sde_hw_intf *ctx,
	if (p->wide_bus_en)
		intf_cfg2 |= BIT(0);

	if (ctx->cfg.split_link_en)
		SDE_REG_WRITE(c, INTF_REG_SPLIT_LINK, 0x3);

	SDE_REG_WRITE(c, INTF_HSYNC_CTL, hsync_ctl);
	SDE_REG_WRITE(c, INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period);
	SDE_REG_WRITE(c, INTF_VSYNC_PULSE_WIDTH_F0,
@@ -396,6 +399,9 @@ static void sde_hw_intf_bind_pingpong_blk(
	else
		mux_cfg |= 0xf;

	if (intf->cfg.split_link_en)
		mux_cfg = 0x60000;

	SDE_REG_WRITE(c, INTF_MUX, mux_cfg);
}

Loading