Commit 7eacba9a authored by AngeloGioacchino Del Regno's avatar AngeloGioacchino Del Regno Committed by Chun-Kuang Hu

drm/mediatek: dp: Add .wait_hpd_asserted() for AUX bus

In order to support usecases in which the panel regulator can be
switched on and off to save power, and usecases in which the panel
regulator is off at boot, add a .wait_hpd_asserted() callback for
the AUX bus: this will make sure to wait until the panel is fully
ready after power-on before trying to communicate with it.

Also, parse the eDP display capabilities in that callback, so that
we can also avoid using the .get_edid() callback from this bridge.

Since at this point the hpd machinery is performed in the new hpd
callback and the detection and edid reading are done outside of
this driver, assign the DRM_BRIDGE_OP_{DETECT, EDID, HPD} ops and
register the bridge unconditionally at probe time only if we are
probing full DisplayPort and not eDP while, for the latter, we
register the bridge in the .done_probing() callback and only if
the panel was found and triggered HPD.
Signed-off-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Tested-by: default avatarChen-Yu Tsai <wenst@chromium.org>
Reviewed-by: default avatarAlexandre Mergnat <amergnat@baylibre.com>
Reviewed-by: default avatarCK Hu <ck.hu@mediatek.com>
Link: https://patchwork.kernel.org/project/dri-devel/patch/20230725073234.55892-11-angelogioacchino.delregno@collabora.com/Signed-off-by: default avatarChun-Kuang Hu <chunkuang.hu@kernel.org>
parent caf2ae48
...@@ -1920,6 +1920,31 @@ static irqreturn_t mtk_dp_hpd_event(int hpd, void *dev) ...@@ -1920,6 +1920,31 @@ static irqreturn_t mtk_dp_hpd_event(int hpd, void *dev)
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
} }
static int mtk_dp_wait_hpd_asserted(struct drm_dp_aux *mtk_aux, unsigned long wait_us)
{
struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
u32 val;
int ret;
ret = regmap_read_poll_timeout(mtk_dp->regs, MTK_DP_TRANS_P0_3414,
val, !!(val & HPD_DB_DP_TRANS_P0_MASK),
wait_us / 100, wait_us);
if (ret) {
mtk_dp->train_info.cable_plugged_in = false;
return ret;
}
mtk_dp->train_info.cable_plugged_in = true;
ret = mtk_dp_parse_capabilities(mtk_dp);
if (ret) {
drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
return ret;
}
return 0;
}
static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp,
struct platform_device *pdev) struct platform_device *pdev)
{ {
...@@ -2532,6 +2557,12 @@ static int mtk_dp_edp_link_panel(struct drm_dp_aux *mtk_aux) ...@@ -2532,6 +2557,12 @@ static int mtk_dp_edp_link_panel(struct drm_dp_aux *mtk_aux)
mtk_dp->next_bridge = NULL; mtk_dp->next_bridge = NULL;
return ret; return ret;
} }
/* For eDP, we add the bridge only if the panel was found */
ret = devm_drm_bridge_add(dev, &mtk_dp->bridge);
if (ret)
return ret;
return 0; return 0;
} }
...@@ -2560,6 +2591,7 @@ static int mtk_dp_probe(struct platform_device *pdev) ...@@ -2560,6 +2591,7 @@ static int mtk_dp_probe(struct platform_device *pdev)
mtk_dp->aux.name = "aux_mtk_dp"; mtk_dp->aux.name = "aux_mtk_dp";
mtk_dp->aux.dev = dev; mtk_dp->aux.dev = dev;
mtk_dp->aux.transfer = mtk_dp_aux_transfer; mtk_dp->aux.transfer = mtk_dp_aux_transfer;
mtk_dp->aux.wait_hpd_asserted = mtk_dp_wait_hpd_asserted;
drm_dp_aux_init(&mtk_dp->aux); drm_dp_aux_init(&mtk_dp->aux);
spin_lock_init(&mtk_dp->irq_thread_lock); spin_lock_init(&mtk_dp->irq_thread_lock);
...@@ -2592,15 +2624,8 @@ static int mtk_dp_probe(struct platform_device *pdev) ...@@ -2592,15 +2624,8 @@ static int mtk_dp_probe(struct platform_device *pdev)
mtk_dp->bridge.funcs = &mtk_dp_bridge_funcs; mtk_dp->bridge.funcs = &mtk_dp_bridge_funcs;
mtk_dp->bridge.of_node = dev->of_node; mtk_dp->bridge.of_node = dev->of_node;
mtk_dp->bridge.ops =
DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
mtk_dp->bridge.type = mtk_dp->data->bridge_type; mtk_dp->bridge.type = mtk_dp->data->bridge_type;
ret = devm_drm_bridge_add(dev, &mtk_dp->bridge);
if (ret)
return dev_err_probe(dev, ret, "Failed to add bridge\n");
mtk_dp->need_debounce = true; mtk_dp->need_debounce = true;
timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0); timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0);
...@@ -2639,6 +2664,12 @@ static int mtk_dp_probe(struct platform_device *pdev) ...@@ -2639,6 +2664,12 @@ static int mtk_dp_probe(struct platform_device *pdev)
return ret; return ret;
} }
} }
} else {
mtk_dp->bridge.ops = DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
ret = devm_drm_bridge_add(dev, &mtk_dp->bridge);
if (ret)
return dev_err_probe(dev, ret, "Failed to add bridge\n");
} }
pm_runtime_enable(dev); pm_runtime_enable(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment