diff options
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c')
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c index 05e48cf4ec1d..ad19330de61a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -2,6 +2,8 @@ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ +#include <linux/bitfield.h> + #include <drm/drm_managed.h> #include "dpu_hwio.h" @@ -107,8 +109,8 @@ static void dpu_hw_get_danger_status(struct dpu_hw_mdp *mdp, status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x3; } -static void dpu_hw_setup_vsync_source(struct dpu_hw_mdp *mdp, - struct dpu_vsync_source_cfg *cfg) +static void dpu_hw_setup_wd_timer(struct dpu_hw_mdp *mdp, + struct dpu_vsync_source_cfg *cfg) { struct dpu_hw_blk_reg_map *c; u32 reg, wd_load_value, wd_ctl, wd_ctl2; @@ -163,8 +165,8 @@ static void dpu_hw_setup_vsync_source(struct dpu_hw_mdp *mdp, } } -static void dpu_hw_setup_vsync_source_and_vsync_sel(struct dpu_hw_mdp *mdp, - struct dpu_vsync_source_cfg *cfg) +static void dpu_hw_setup_vsync_sel(struct dpu_hw_mdp *mdp, + struct dpu_vsync_source_cfg *cfg) { struct dpu_hw_blk_reg_map *c; u32 reg, i; @@ -187,7 +189,7 @@ static void dpu_hw_setup_vsync_source_and_vsync_sel(struct dpu_hw_mdp *mdp, } DPU_REG_WRITE(c, MDP_VSYNC_SEL, reg); - dpu_hw_setup_vsync_source(mdp, cfg); + dpu_hw_setup_wd_timer(mdp, cfg); } static void dpu_hw_get_safe_status(struct dpu_hw_mdp *mdp, @@ -231,28 +233,68 @@ static void dpu_hw_intf_audio_select(struct dpu_hw_mdp *mdp) DPU_REG_WRITE(c, HDMI_DP_CORE_SELECT, 0x1); } +static void dpu_hw_dp_phy_intf_sel(struct dpu_hw_mdp *mdp, + enum dpu_dp_phy_sel phys[2]) +{ + struct dpu_hw_blk_reg_map *c = &mdp->hw; + unsigned int intf; + u32 sel = 0; + + sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_INTF0, phys[0]); + sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_INTF1, phys[1]); + + for (intf = 0; intf < 2; intf++) { + switch (phys[intf]) { + case DPU_DP_PHY_0: + sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_PHY0, intf + 1); + break; + case DPU_DP_PHY_1: + sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_PHY1, intf + 1); + break; + case DPU_DP_PHY_2: + sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_PHY2, intf + 1); + break; + default: + /* ignore */ + break; + } + } + + DPU_REG_WRITE(c, MDP_DP_PHY_INTF_SEL, sel); +} + static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops, - unsigned long cap) + unsigned long cap, const struct dpu_mdss_version *mdss_rev) { ops->setup_split_pipe = dpu_hw_setup_split_pipe; ops->setup_clk_force_ctrl = dpu_hw_setup_clk_force_ctrl; ops->get_danger_status = dpu_hw_get_danger_status; if (cap & BIT(DPU_MDP_VSYNC_SEL)) - ops->setup_vsync_source = dpu_hw_setup_vsync_source_and_vsync_sel; + ops->setup_vsync_source = dpu_hw_setup_vsync_sel; else - ops->setup_vsync_source = dpu_hw_setup_vsync_source; + ops->setup_vsync_source = dpu_hw_setup_wd_timer; ops->get_safe_status = dpu_hw_get_safe_status; + if (mdss_rev->core_major_ver >= 5) + ops->dp_phy_intf_sel = dpu_hw_dp_phy_intf_sel; + if (cap & BIT(DPU_MDP_AUDIO_SELECT)) ops->intf_audio_select = dpu_hw_intf_audio_select; } +/** + * dpu_hw_mdptop_init - initializes the top driver for the passed config + * @dev: Corresponding device for devres management + * @cfg: MDP TOP configuration from catalog + * @addr: Mapped register io address of MDP + * @mdss_rev: dpu core's major and minor versions + */ struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev, const struct dpu_mdp_cfg *cfg, void __iomem *addr, - const struct dpu_mdss_cfg *m) + const struct dpu_mdss_version *mdss_rev) { struct dpu_hw_mdp *mdp; @@ -270,7 +312,7 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev, * Assign ops */ mdp->caps = cfg; - _setup_mdp_ops(&mdp->ops, mdp->caps->features); + _setup_mdp_ops(&mdp->ops, mdp->caps->features, mdss_rev); return mdp; } |