drm/mediatek: dp: Add MT8195 External DisplayPort support
Add External DisplayPort support to the MT8195 eDP driver. Signed-off-by: Guillaume Ranquet <granquet@baylibre.com> Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220901044149.16782-9-rex-bc.chen@mediatek.com
This commit is contained in:
parent
86e77a1f0a
commit
d9e6ea02fc
@ -35,6 +35,7 @@
|
||||
|
||||
#define MTK_DP_SIP_CONTROL_AARCH32 MTK_SIP_SMC_CMD(0x523)
|
||||
#define MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE (BIT(0) | BIT(5))
|
||||
#define MTK_DP_SIP_ATF_VIDEO_UNMUTE BIT(5)
|
||||
|
||||
#define MTK_DP_THREAD_CABLE_STATE_CHG BIT(0)
|
||||
#define MTK_DP_THREAD_HPD_EVENT BIT(1)
|
||||
@ -199,6 +200,89 @@ static const struct mtk_dp_efuse_fmt mt8195_edp_efuse_fmt[MTK_DP_CAL_MAX] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mtk_dp_efuse_fmt mt8195_dp_efuse_fmt[MTK_DP_CAL_MAX] = {
|
||||
[MTK_DP_CAL_GLB_BIAS_TRIM] = {
|
||||
.idx = 0,
|
||||
.shift = 27,
|
||||
.mask = 0x1f,
|
||||
.min_val = 1,
|
||||
.max_val = 0x1e,
|
||||
.default_val = 0xf,
|
||||
},
|
||||
[MTK_DP_CAL_CLKTX_IMPSE] = {
|
||||
.idx = 0,
|
||||
.shift = 13,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_0] = {
|
||||
.idx = 1,
|
||||
.shift = 28,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_1] = {
|
||||
.idx = 1,
|
||||
.shift = 20,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_2] = {
|
||||
.idx = 1,
|
||||
.shift = 12,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_PMOS_3] = {
|
||||
.idx = 1,
|
||||
.shift = 4,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_0] = {
|
||||
.idx = 1,
|
||||
.shift = 24,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_1] = {
|
||||
.idx = 1,
|
||||
.shift = 16,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_2] = {
|
||||
.idx = 1,
|
||||
.shift = 8,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
[MTK_DP_CAL_LN_TX_IMPSEL_NMOS_3] = {
|
||||
.idx = 1,
|
||||
.shift = 0,
|
||||
.mask = 0xf,
|
||||
.min_val = 1,
|
||||
.max_val = 0xe,
|
||||
.default_val = 0x8,
|
||||
},
|
||||
};
|
||||
|
||||
static struct regmap_config mtk_dp_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
@ -1479,6 +1563,50 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge)
|
||||
{
|
||||
struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
bool enabled = mtk_dp->enabled;
|
||||
u8 sink_count = 0;
|
||||
|
||||
if (mtk_dp->train_info.cable_plugged_in) {
|
||||
if (!enabled) {
|
||||
/* power on aux */
|
||||
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
|
||||
DP_PWR_STATE_BANDGAP_TPLL_LANE,
|
||||
DP_PWR_STATE_MASK);
|
||||
|
||||
/* power on panel */
|
||||
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
|
||||
usleep_range(2000, 5000);
|
||||
}
|
||||
/*
|
||||
* Some dongles still source HPD when they do not connect to any
|
||||
* sink device. To avoid this, we need to read the sink count
|
||||
* to make sure we do connect to sink devices. After this detect
|
||||
* function, we just need to check the HPD connection to check
|
||||
* whether we connect to a sink device.
|
||||
*/
|
||||
drm_dp_dpcd_readb(&mtk_dp->aux, DP_SINK_COUNT, &sink_count);
|
||||
if (DP_GET_SINK_COUNT(sink_count))
|
||||
ret = connector_status_connected;
|
||||
|
||||
if (!enabled) {
|
||||
/* power off panel */
|
||||
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
/* power off aux */
|
||||
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
|
||||
DP_PWR_STATE_BANDGAP_TPLL,
|
||||
DP_PWR_STATE_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
@ -1865,6 +1993,7 @@ static const struct drm_bridge_funcs mtk_dp_bridge_funcs = {
|
||||
.atomic_disable = mtk_dp_bridge_atomic_disable,
|
||||
.mode_valid = mtk_dp_bridge_mode_valid,
|
||||
.get_edid = mtk_dp_get_edid,
|
||||
.detect = mtk_dp_bdg_detect,
|
||||
};
|
||||
|
||||
static int mtk_dp_probe(struct platform_device *pdev)
|
||||
@ -1991,11 +2120,21 @@ static const struct mtk_dp_data mt8195_edp_data = {
|
||||
.efuse_fmt = mt8195_edp_efuse_fmt,
|
||||
};
|
||||
|
||||
static const struct mtk_dp_data mt8195_dp_data = {
|
||||
.bridge_type = DRM_MODE_CONNECTOR_DisplayPort,
|
||||
.smc_cmd = MTK_DP_SIP_ATF_VIDEO_UNMUTE,
|
||||
.efuse_fmt = mt8195_dp_efuse_fmt,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_dp_of_match[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt8195-edp-tx",
|
||||
.data = &mt8195_edp_data,
|
||||
},
|
||||
{
|
||||
.compatible = "mediatek,mt8195-dp-tx",
|
||||
.data = &mt8195_dp_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_dp_of_match);
|
||||
|
Loading…
Reference in New Issue
Block a user