mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-01 15:14:52 +00:00
drm/hisilicon/hibmc: Enable this hot plug detect of irq feature
Add HPD interrupt enable functions in drm framework, and also add detect_ctx functions. Because of the debouncing when HPD pulled out, add 200 ms delay in detect. Add link reset process to reset link status when a new connector pulgged in. Signed-off-by: Baihan Li <libaihan@huawei.com> Signed-off-by: Yongbang Shi <shiyongbang@huawei.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Link: https://lore.kernel.org/r/20250331074212.3370287-8-shiyongbang@huawei.com Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
This commit is contained in:
parent
2f6182616c
commit
3c7623fb5b
@ -16,5 +16,6 @@
|
||||
#define HIBMC_DP_SYNC_EN_MASK 0x3
|
||||
#define HIBMC_DP_LINK_RATE_CAL 27
|
||||
#define HIBMC_DP_SYNC_DELAY(lanes) ((lanes) == 0x2 ? 86 : 46)
|
||||
#define HIBMC_DP_INT_ENABLE 0xc
|
||||
|
||||
#endif
|
||||
|
@ -189,6 +189,36 @@ int hibmc_dp_hw_init(struct hibmc_dp *dp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hibmc_dp_enable_int(struct hibmc_dp *dp)
|
||||
{
|
||||
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
|
||||
|
||||
writel(HIBMC_DP_INT_ENABLE, dp_dev->base + HIBMC_DP_INTR_ENABLE);
|
||||
}
|
||||
|
||||
void hibmc_dp_disable_int(struct hibmc_dp *dp)
|
||||
{
|
||||
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
|
||||
|
||||
writel(0, dp_dev->base + HIBMC_DP_INTR_ENABLE);
|
||||
writel(HIBMC_DP_INT_RST, dp_dev->base + HIBMC_DP_INTR_ORIGINAL_STATUS);
|
||||
}
|
||||
|
||||
void hibmc_dp_hpd_cfg(struct hibmc_dp *dp)
|
||||
{
|
||||
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
|
||||
|
||||
hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_SYNC_LEN_SEL, 0x0);
|
||||
hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_TIMER_TIMEOUT, 0x1);
|
||||
hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_MIN_PULSE_NUM, 0x9);
|
||||
writel(HIBMC_DP_HDCP, dp_dev->base + HIBMC_DP_HDCP_CFG);
|
||||
writel(0, dp_dev->base + HIBMC_DP_INTR_ENABLE);
|
||||
writel(HIBMC_DP_INT_RST, dp_dev->base + HIBMC_DP_INTR_ORIGINAL_STATUS);
|
||||
writel(HIBMC_DP_INT_ENABLE, dp_dev->base + HIBMC_DP_INTR_ENABLE);
|
||||
writel(HIBMC_DP_DPTX_RST, dp_dev->base + HIBMC_DP_DPTX_RST_CTRL);
|
||||
writel(HIBMC_DP_CLK_EN, dp_dev->base + HIBMC_DP_DPTX_CLK_CTRL);
|
||||
}
|
||||
|
||||
void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable)
|
||||
{
|
||||
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
|
||||
@ -227,6 +257,12 @@ int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hibmc_dp_reset_link(struct hibmc_dp *dp)
|
||||
{
|
||||
dp->dp_dev->link.status.clock_recovered = false;
|
||||
dp->dp_dev->link.status.channel_equalized = false;
|
||||
}
|
||||
|
||||
static const struct hibmc_dp_color_raw g_rgb_raw[] = {
|
||||
{CBAR_COLOR_BAR, 0x000, 0x000, 0x000},
|
||||
{CBAR_WHITE, 0xfff, 0xfff, 0xfff},
|
||||
|
@ -49,11 +49,16 @@ struct hibmc_dp {
|
||||
void __iomem *mmio;
|
||||
struct drm_dp_aux aux;
|
||||
struct hibmc_dp_cbar_cfg cfg;
|
||||
u32 irq_status;
|
||||
};
|
||||
|
||||
int hibmc_dp_hw_init(struct hibmc_dp *dp);
|
||||
int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode);
|
||||
void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable);
|
||||
void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg);
|
||||
void hibmc_dp_reset_link(struct hibmc_dp *dp);
|
||||
void hibmc_dp_hpd_cfg(struct hibmc_dp *dp);
|
||||
void hibmc_dp_enable_int(struct hibmc_dp *dp);
|
||||
void hibmc_dp_disable_int(struct hibmc_dp *dp);
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "hibmc_drm_drv.h"
|
||||
#include "dp/dp_hw.h"
|
||||
|
||||
#define DP_MASKED_SINK_HPD_PLUG_INT BIT(2)
|
||||
|
||||
static int hibmc_dp_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
const struct drm_edid *drm_edid;
|
||||
@ -29,14 +31,25 @@ static int hibmc_dp_connector_get_modes(struct drm_connector *connector)
|
||||
return count;
|
||||
}
|
||||
|
||||
static int hibmc_dp_detect(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx, bool force)
|
||||
{
|
||||
mdelay(200);
|
||||
|
||||
return drm_connector_helper_detect_from_ddc(connector, ctx, force);
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs hibmc_dp_conn_helper_funcs = {
|
||||
.get_modes = hibmc_dp_connector_get_modes,
|
||||
.detect_ctx = hibmc_dp_detect,
|
||||
};
|
||||
|
||||
static int hibmc_dp_late_register(struct drm_connector *connector)
|
||||
{
|
||||
struct hibmc_dp *dp = to_hibmc_dp(connector);
|
||||
|
||||
hibmc_dp_enable_int(dp);
|
||||
|
||||
return drm_dp_aux_register(&dp->aux);
|
||||
}
|
||||
|
||||
@ -45,6 +58,8 @@ static void hibmc_dp_early_unregister(struct drm_connector *connector)
|
||||
struct hibmc_dp *dp = to_hibmc_dp(connector);
|
||||
|
||||
drm_dp_aux_unregister(&dp->aux);
|
||||
|
||||
hibmc_dp_disable_int(dp);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs hibmc_dp_conn_funcs = {
|
||||
@ -96,6 +111,31 @@ static const struct drm_encoder_helper_funcs hibmc_dp_encoder_helper_funcs = {
|
||||
.atomic_disable = hibmc_dp_encoder_disable,
|
||||
};
|
||||
|
||||
irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *)arg;
|
||||
struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
|
||||
int idx;
|
||||
|
||||
if (!drm_dev_enter(dev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
if (priv->dp.irq_status & DP_MASKED_SINK_HPD_PLUG_INT) {
|
||||
drm_dbg_dp(&priv->dev, "HPD IN isr occur!\n");
|
||||
hibmc_dp_hpd_cfg(&priv->dp);
|
||||
} else {
|
||||
drm_dbg_dp(&priv->dev, "HPD OUT isr occur!\n");
|
||||
hibmc_dp_reset_link(&priv->dp);
|
||||
}
|
||||
|
||||
if (dev->registered)
|
||||
drm_connector_helper_hpd_irq_event(&priv->dp.connector);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int hibmc_dp_init(struct hibmc_drm_private *priv)
|
||||
{
|
||||
struct drm_device *dev = &priv->dev;
|
||||
@ -136,5 +176,7 @@ int hibmc_dp_init(struct hibmc_drm_private *priv)
|
||||
|
||||
drm_connector_attach_encoder(connector, encoder);
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,4 +71,6 @@ int hibmc_dp_init(struct hibmc_drm_private *priv);
|
||||
|
||||
void hibmc_debugfs_init(struct drm_connector *connector, struct dentry *root);
|
||||
|
||||
irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user