Skip to content

Commit be3415c

Browse files
committed
drm/msm/dpu: Configure DP INTF/PHY selector
Some platforms provides a mechanism for configuring the mapping between (one or two) DisplayPort intfs and their PHYs. In particular SC8180X requires this to be configured, since on this platform there are fewer controllers than PHYs. The change implements the logic for optionally configuring which PHY each of the DP INTFs should be connected to and marks the SC8180X DPU to program 2 entries. For now the request is simply to program the mapping 1:1, any support for alternative mappings is left until the use case arrise. Note that e.g. msm-4.14 unconditionally maps INTF 0 to PHY 0 on all platforms, so perhaps this is needed in order to get DisplayPort working on some other platforms as well. Co-developed-by: Bjorn Andersson <[email protected]> Signed-off-by: Bjorn Andersson <[email protected]> Signed-off-by: Dmitry Baryshkov <[email protected]> Reviewed-by: Abhinav Kumar <[email protected]> Patchwork: https://patchwork.freedesktop.org/patch/600895/ Link: https://lore.kernel.org/r/[email protected]
1 parent a14b929 commit be3415c

File tree

4 files changed

+72
-6
lines changed

4 files changed

+72
-6
lines changed

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
33
*/
44

5+
#include <linux/bitfield.h>
6+
57
#include <drm/drm_managed.h>
68

79
#include "dpu_hwio.h"
@@ -231,8 +233,38 @@ static void dpu_hw_intf_audio_select(struct dpu_hw_mdp *mdp)
231233
DPU_REG_WRITE(c, HDMI_DP_CORE_SELECT, 0x1);
232234
}
233235

236+
static void dpu_hw_dp_phy_intf_sel(struct dpu_hw_mdp *mdp,
237+
enum dpu_dp_phy_sel phys[2])
238+
{
239+
struct dpu_hw_blk_reg_map *c = &mdp->hw;
240+
unsigned int intf;
241+
u32 sel = 0;
242+
243+
sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_INTF0, phys[0]);
244+
sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_INTF1, phys[1]);
245+
246+
for (intf = 0; intf < 2; intf++) {
247+
switch (phys[intf]) {
248+
case DPU_DP_PHY_0:
249+
sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_PHY0, intf + 1);
250+
break;
251+
case DPU_DP_PHY_1:
252+
sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_PHY1, intf + 1);
253+
break;
254+
case DPU_DP_PHY_2:
255+
sel |= FIELD_PREP(MDP_DP_PHY_INTF_SEL_PHY2, intf + 1);
256+
break;
257+
default:
258+
/* ignore */
259+
break;
260+
}
261+
}
262+
263+
DPU_REG_WRITE(c, MDP_DP_PHY_INTF_SEL, sel);
264+
}
265+
234266
static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
235-
unsigned long cap)
267+
unsigned long cap, const struct dpu_mdss_version *mdss_rev)
236268
{
237269
ops->setup_split_pipe = dpu_hw_setup_split_pipe;
238270
ops->setup_clk_force_ctrl = dpu_hw_setup_clk_force_ctrl;
@@ -245,14 +277,17 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
245277

246278
ops->get_safe_status = dpu_hw_get_safe_status;
247279

280+
if (mdss_rev->core_major_ver >= 5)
281+
ops->dp_phy_intf_sel = dpu_hw_dp_phy_intf_sel;
282+
248283
if (cap & BIT(DPU_MDP_AUDIO_SELECT))
249284
ops->intf_audio_select = dpu_hw_intf_audio_select;
250285
}
251286

252287
struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
253288
const struct dpu_mdp_cfg *cfg,
254289
void __iomem *addr,
255-
const struct dpu_mdss_cfg *m)
290+
const struct dpu_mdss_version *mdss_rev)
256291
{
257292
struct dpu_hw_mdp *mdp;
258293

@@ -270,7 +305,7 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
270305
* Assign ops
271306
*/
272307
mdp->caps = cfg;
273-
_setup_mdp_ops(&mdp->ops, mdp->caps->features);
308+
_setup_mdp_ops(&mdp->ops, mdp->caps->features, mdss_rev);
274309

275310
return mdp;
276311
}

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ struct dpu_vsync_source_cfg {
6767
enum dpu_vsync_source vsync_source;
6868
};
6969

70+
enum dpu_dp_phy_sel {
71+
DPU_DP_PHY_NONE,
72+
DPU_DP_PHY_0,
73+
DPU_DP_PHY_1,
74+
DPU_DP_PHY_2,
75+
};
76+
7077
/**
7178
* struct dpu_hw_mdp_ops - interface to the MDP TOP Hw driver functions
7279
* Assumption is these functions will be called after clocks are enabled.
@@ -125,6 +132,13 @@ struct dpu_hw_mdp_ops {
125132
void (*get_safe_status)(struct dpu_hw_mdp *mdp,
126133
struct dpu_danger_safe_status *status);
127134

135+
/**
136+
* dp_phy_intf_sel - configure intf to phy mapping
137+
* @mdp: mdp top context driver
138+
* @phys: list of phys the DP interfaces should be connected to. 0 disables the INTF.
139+
*/
140+
void (*dp_phy_intf_sel)(struct dpu_hw_mdp *mdp, enum dpu_dp_phy_sel phys[2]);
141+
128142
/**
129143
* intf_audio_select - select the external interface for audio
130144
* @mdp: mdp top context driver
@@ -148,12 +162,12 @@ struct dpu_hw_mdp {
148162
* @dev: Corresponding device for devres management
149163
* @cfg: MDP TOP configuration from catalog
150164
* @addr: Mapped register io address of MDP
151-
* @m: Pointer to mdss catalog data
165+
* @mdss_rev: dpu core's major and minor versions
152166
*/
153167
struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
154168
const struct dpu_mdp_cfg *cfg,
155169
void __iomem *addr,
156-
const struct dpu_mdss_cfg *m);
170+
const struct dpu_mdss_version *mdss_rev);
157171

158172
void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp);
159173

drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@
6060
#define MDP_WD_TIMER_4_LOAD_VALUE 0x448
6161
#define DCE_SEL 0x450
6262

63+
#define MDP_DP_PHY_INTF_SEL 0x460
64+
#define MDP_DP_PHY_INTF_SEL_INTF0 GENMASK(2, 0)
65+
#define MDP_DP_PHY_INTF_SEL_INTF1 GENMASK(5, 3)
66+
#define MDP_DP_PHY_INTF_SEL_PHY0 GENMASK(8, 6)
67+
#define MDP_DP_PHY_INTF_SEL_PHY1 GENMASK(11, 9)
68+
#define MDP_DP_PHY_INTF_SEL_PHY2 GENMASK(14, 12)
69+
6370
#define MDP_PERIPH_TOP0 MDP_WD_TIMER_0_CTL
6471
#define MDP_PERIPH_TOP0_END CLK_CTRL3
6572

drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
11461146
dpu_kms->hw_mdp = dpu_hw_mdptop_init(dev,
11471147
dpu_kms->catalog->mdp,
11481148
dpu_kms->mmio,
1149-
dpu_kms->catalog);
1149+
dpu_kms->catalog->mdss_ver);
11501150
if (IS_ERR(dpu_kms->hw_mdp)) {
11511151
rc = PTR_ERR(dpu_kms->hw_mdp);
11521152
DPU_ERROR("failed to get hw_mdp: %d\n", rc);
@@ -1181,6 +1181,16 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
11811181
goto err_pm_put;
11821182
}
11831183

1184+
/*
1185+
* We need to program DP <-> PHY relationship only for SC8180X since it
1186+
* has fewer DP controllers than DP PHYs.
1187+
* If any other platform requires the same kind of programming, or if
1188+
* the INTF <->DP relationship isn't static anymore, this needs to be
1189+
* configured through the DT.
1190+
*/
1191+
if (of_device_is_compatible(dpu_kms->pdev->dev.of_node, "qcom,sc8180x-dpu"))
1192+
dpu_kms->hw_mdp->ops.dp_phy_intf_sel(dpu_kms->hw_mdp, (unsigned int[]){ 1, 2, });
1193+
11841194
dpu_kms->hw_intr = dpu_hw_intr_init(dev, dpu_kms->mmio, dpu_kms->catalog);
11851195
if (IS_ERR(dpu_kms->hw_intr)) {
11861196
rc = PTR_ERR(dpu_kms->hw_intr);

0 commit comments

Comments
 (0)