Loading msm/dsi/dsi_phy.c +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> Loading Loading @@ -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; Loading msm/dsi/dsi_phy.h +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_ Loading Loading @@ -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 Loading @@ -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; Loading msm/dsi/dsi_phy_hw.h +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_ Loading Loading @@ -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). Loading @@ -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; Loading msm/dsi/dsi_phy_hw_v4_0.c +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> Loading Loading @@ -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. Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -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) Loading Loading @@ -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); Loading Loading @@ -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, Loading @@ -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); Loading Loading @@ -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. Loading @@ -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; } Loading msm/sde/sde_encoder_phys_vid.c +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__ Loading Loading @@ -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"); Loading @@ -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 Loading
msm/dsi/dsi_phy.c +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> Loading Loading @@ -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; Loading
msm/dsi/dsi_phy.h +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_ Loading Loading @@ -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 Loading @@ -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; Loading
msm/dsi/dsi_phy_hw.h +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_ Loading Loading @@ -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). Loading @@ -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; Loading
msm/dsi/dsi_phy_hw_v4_0.c +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> Loading Loading @@ -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. Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -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) Loading Loading @@ -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); Loading Loading @@ -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, Loading @@ -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); Loading Loading @@ -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. Loading @@ -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; } Loading
msm/sde/sde_encoder_phys_vid.c +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__ Loading Loading @@ -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"); Loading @@ -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