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

Commit 86fe4ea2 authored by Linux Build Service Account's avatar Linux Build Service Account
Browse files

Merge ce33c52e on remote branch

Change-Id: I33548851d465f24ce76e52a4fbe9fdc5a677798a
parents dedc422e ce33c52e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/of_device.h>
@@ -880,8 +881,8 @@ int dsi_phy_enable(struct msm_dsi_phy *phy,

	memcpy(&phy->mode, &config->video_timing, sizeof(phy->mode));
	memcpy(&phy->cfg.lane_map, &config->lane_map, sizeof(config->lane_map));
	phy->data_lanes = config->common_config.data_lanes;
	phy->dst_format = config->common_config.dst_format;
	phy->cfg.data_lanes = config->common_config.data_lanes;
	phy->cfg.pll_source = pll_source;
	phy->cfg.bit_clk_rate_hz = config->bit_clk_rate_hz;

+1 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
 */

#ifndef _DSI_PHY_H_
@@ -68,7 +69,6 @@ enum phy_ulps_return_type {
 * @power_state:       True if PHY is powered on.
 * @dsi_phy_state:     PHY state information.
 * @mode:              Current mode.
 * @data_lanes:        Number of data lanes used.
 * @dst_format:        Destination format.
 * @allow_phy_power_off: True if PHY is allowed to power off when idle
 * @regulator_min_datarate_bps: Minimum per lane data rate to turn on regulator
@@ -92,7 +92,6 @@ struct msm_dsi_phy {
	enum phy_engine_state dsi_phy_state;
	bool power_state;
	struct dsi_mode_info mode;
	enum dsi_data_lanes data_lanes;
	enum dsi_pixel_format dst_format;

	bool allow_phy_power_off;
+3 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
 */

#ifndef _DSI_PHY_HW_H_
@@ -96,6 +97,7 @@ struct dsi_phy_per_lane_cfgs {
 * @is_phy_timing_present:	Boolean whether phy timings are defined.
 * @regulators:       Regulator settings for lanes.
 * @pll_source:       PLL source.
 * @data_lanes:       Number of data lanes used.
 * @lane_map:         DSI logical to PHY lane mapping.
 * @force_clk_lane_hs:Boolean whether to force clock lane in HS mode.
 * @phy_type:         Phy-type (Dphy/Cphy).
@@ -112,6 +114,7 @@ struct dsi_phy_cfg {
	bool force_clk_lane_hs;
	enum dsi_phy_type phy_type;
	unsigned long bit_clk_rate_hz;
	u32 data_lanes;
};

struct dsi_phy_hw;
+33 −7
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/math64.h>
@@ -202,6 +203,26 @@ void dsi_phy_hw_v4_0_commit_phy_timing(struct dsi_phy_hw *phy,
	DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_13, timing->lane_v4[13]);
}

/**
 * calc_cmn_lane_ctrl0() - Calculate the value to be set for
 *			   DSIPHY_CMN_LANE_CTRL0 register.
 * @cfg:      Per lane configurations for timing, strength and lane
 *	      configurations.
 */
static inline int dsi_phy_hw_calc_cmn_lane_ctrl0(struct dsi_phy_cfg *cfg)
{
	u32 cmn_lane_ctrl0 = 0;

	/* Only enable lanes that are required */
	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(0) : 0);
	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(1) : 0);
	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(2) : 0);
	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(3) : 0);
	cmn_lane_ctrl0 |= BIT(4);

	return cmn_lane_ctrl0;
}

/**
 * cphy_enable() - Enable CPHY hardware
 * @phy:      Pointer to DSI PHY hardware object.
@@ -220,6 +241,7 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy,
	u32 glbl_hstx_str_ctrl_0 = 0;
	u32 glbl_rescode_top_ctrl = 0;
	u32 glbl_rescode_bot_ctrl = 0;
	u32 cmn_lane_ctrl0 = 0;

	if (phy->version == DSI_PHY_VERSION_4_1) {
		glbl_rescode_top_ctrl = 0x00;
@@ -271,7 +293,9 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy,
	/* Remove power down from all blocks */
	DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);

	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x17);
	cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);

	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0);

	switch (cfg->pll_source) {
	case DSI_PLL_SOURCE_STANDALONE:
@@ -321,6 +345,7 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
	u32 glbl_hstx_str_ctrl_0 = 0;
	u32 glbl_rescode_top_ctrl = 0;
	u32 glbl_rescode_bot_ctrl = 0;
	u32 cmn_lane_ctrl0 = 0;

	/* Alter PHY configurations if data rate less than 1.5GHZ*/
	if (cfg->bit_clk_rate_hz <= 1500000000)
@@ -377,7 +402,9 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
	/* Remove power down from all blocks */
	DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);

	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F);
	cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);

	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0);

	/* Select full-rate mode */
	DSI_W32(phy, DSIPHY_CMN_CTRL_2, 0x40);
@@ -652,8 +679,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
					struct dsi_phy_cfg *cfg, bool is_master)
{
	u32 reg;
	bool is_cphy = (cfg->phy_type == DSI_PHY_TYPE_CPHY) ?
			true : false;
	u32 cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);

	if (is_master) {
		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19,
@@ -679,7 +705,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
			  cfg->timing.lane_v4[12], cfg->timing.lane_v4[13]);
		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26,
			  DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0,
			  0x7f, is_cphy ? 0x17 : 0x1f);
			  0x7f, cmn_lane_ctrl0);

	} else {
		reg = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1);
@@ -714,7 +740,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
			  cfg->timing.lane_v4[13], 0x7f);
		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9,
			  DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2,
			  is_cphy ? 0x17 : 0x1f, 0x40);
			  cmn_lane_ctrl0, 0x40);
		/*
		 * fill with dummy register writes since controller will blindly
		 * send these values to DSI PHY.
@@ -723,7 +749,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
		while (reg <= DSI_DYN_REFRESH_PLL_CTRL29) {
			DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg,
				  DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_0,
				  is_cphy ? 0x17 : 0x1f, 0x7f);
				  cmn_lane_ctrl0, 0x7f);
			reg += 0x4;
		}

+41 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
 */

#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -1080,12 +1081,47 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
	phys_enc->enable_state = SDE_ENC_DISABLED;
}

static int sde_encoder_phys_vid_poll_for_active_region(
					struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_phys_vid *vid_enc;
	struct intf_timing_params *timing;
	struct drm_display_mode mode;
	u32 line_cnt, v_inactive, poll_time_us, trial = 0;

	if (!phys_enc || !phys_enc->hw_intf ||
				!phys_enc->hw_intf->ops.get_line_count)
		return -EINVAL;

	vid_enc = to_sde_encoder_phys_vid(phys_enc);
	timing = &vid_enc->timing_params;
	mode = phys_enc->cached_mode;

	/* if programmable fetch is not enabled return early */
	if (!programmable_fetch_get_num_lines(vid_enc, timing, false))
		return 0;

	poll_time_us = DIV_ROUND_UP(1000000, mode.vrefresh) / MAX_POLL_CNT;
	v_inactive = timing->v_front_porch + timing->v_back_porch +
						timing->vsync_pulse_width;

	do {
		usleep_range(poll_time_us, poll_time_us + 5);
		line_cnt = phys_enc->hw_intf->ops.get_line_count(
							phys_enc->hw_intf);
		trial++;
	} while ((trial < MAX_POLL_CNT) || (line_cnt < v_inactive));

	return (trial >= MAX_POLL_CNT) ? -ETIMEDOUT : 0;
}

static void sde_encoder_phys_vid_handle_post_kickoff(
		struct sde_encoder_phys *phys_enc)
{
	unsigned long lock_flags;
	struct sde_encoder_phys_vid *vid_enc;
	u32 avr_mode;
	u32 ret;

	if (!phys_enc) {
		SDE_ERROR("invalid encoder\n");
@@ -1108,6 +1144,11 @@ static void sde_encoder_phys_vid_handle_post_kickoff(
				1);
			spin_unlock_irqrestore(phys_enc->enc_spinlock,
				lock_flags);
			ret = sde_encoder_phys_vid_poll_for_active_region(
								     phys_enc);
			if (ret)
				SDE_DEBUG_VIDENC(vid_enc,
				       "poll for active failed ret:%d\n", ret);
		}
		phys_enc->enable_state = SDE_ENC_ENABLED;
	}
Loading