Skip to content

Commit caf2ae4

Browse files
AngeloGioacchino Del RegnoChun-Kuang Hu
authored andcommitted
drm/mediatek: dp: Add support for embedded DisplayPort aux-bus
For the eDP case we can support using aux-bus on MediaTek DP: this gives us the possibility to declare our panel as generic "panel-edp" which will automatically configure the timings and available modes via the EDID that we read from it. To do this, move the panel parsing at the end of the probe function so that the hardware is initialized beforehand and also initialize the DPTX AUX block and power both on as, when we populate the aux-bus, the panel driver will trigger an EDID read to perform panel detection. Last but not least, since now the AUX transfers can happen in the separated aux-bus, it was necessary to add an exclusion for the cable_plugged_in check in `mtk_dp_aux_transfer()` and the easiest way to do this is to simply ignore checking that when the bridge type is eDP. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Tested-by: Chen-Yu Tsai <wenst@chromium.org> Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com> Reviewed-by: CK Hu <ck.hu@mediatek.com> Link: https://patchwork.kernel.org/project/dri-devel/patch/20230725073234.55892-10-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
1 parent 18ccc23 commit caf2ae4

File tree

2 files changed

+79
-14
lines changed

2 files changed

+79
-14
lines changed

drivers/gpu/drm/mediatek/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ config DRM_MEDIATEK_DP
2626
select PHY_MTK_DP
2727
select DRM_DISPLAY_HELPER
2828
select DRM_DISPLAY_DP_HELPER
29+
select DRM_DP_AUX_BUS
2930
help
3031
DRM/KMS Display Port driver for MediaTek SoCs.
3132

drivers/gpu/drm/mediatek/mtk_dp.c

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Copyright (c) 2022 BayLibre
55
*/
66

7+
#include <drm/display/drm_dp_aux_bus.h>
78
#include <drm/display/drm_dp.h>
89
#include <drm/display/drm_dp_helper.h>
910
#include <drm/drm_atomic_helper.h>
@@ -1313,9 +1314,11 @@ static void mtk_dp_power_disable(struct mtk_dp *mtk_dp)
13131314

13141315
static void mtk_dp_initialize_priv_data(struct mtk_dp *mtk_dp)
13151316
{
1317+
bool plugged_in = (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP);
1318+
13161319
mtk_dp->train_info.link_rate = DP_LINK_BW_5_4;
13171320
mtk_dp->train_info.lane_count = mtk_dp->max_lanes;
1318-
mtk_dp->train_info.cable_plugged_in = false;
1321+
mtk_dp->train_info.cable_plugged_in = plugged_in;
13191322

13201323
mtk_dp->info.format = DP_PIXELFORMAT_RGB;
13211324
memset(&mtk_dp->info.vm, 0, sizeof(struct videomode));
@@ -1617,6 +1620,16 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp)
16171620
u8 val;
16181621
ssize_t ret;
16191622

1623+
/*
1624+
* If we're eDP and capabilities were already parsed we can skip
1625+
* reading again because eDP panels aren't hotpluggable hence the
1626+
* caps and training information won't ever change in a boot life
1627+
*/
1628+
if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP &&
1629+
mtk_dp->rx_cap[DP_MAX_LINK_RATE] &&
1630+
mtk_dp->train_info.sink_ssc)
1631+
return 0;
1632+
16201633
ret = drm_dp_read_dpcd_caps(&mtk_dp->aux, mtk_dp->rx_cap);
16211634
if (ret < 0)
16221635
return ret;
@@ -2030,15 +2043,14 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
20302043
static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
20312044
struct drm_dp_aux_msg *msg)
20322045
{
2033-
struct mtk_dp *mtk_dp;
2046+
struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
20342047
bool is_read;
20352048
u8 request;
20362049
size_t accessed_bytes = 0;
20372050
int ret;
20382051

2039-
mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
2040-
2041-
if (!mtk_dp->train_info.cable_plugged_in) {
2052+
if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP &&
2053+
!mtk_dp->train_info.cable_plugged_in) {
20422054
ret = -EAGAIN;
20432055
goto err;
20442056
}
@@ -2501,6 +2513,28 @@ static int mtk_dp_register_phy(struct mtk_dp *mtk_dp)
25012513
return 0;
25022514
}
25032515

2516+
static int mtk_dp_edp_link_panel(struct drm_dp_aux *mtk_aux)
2517+
{
2518+
struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
2519+
struct device *dev = mtk_aux->dev;
2520+
int ret;
2521+
2522+
mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
2523+
2524+
/* Power off the DP and AUX: either detection is done, or no panel present */
2525+
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
2526+
DP_PWR_STATE_BANDGAP_TPLL,
2527+
DP_PWR_STATE_MASK);
2528+
mtk_dp_power_disable(mtk_dp);
2529+
2530+
if (IS_ERR(mtk_dp->next_bridge)) {
2531+
ret = PTR_ERR(mtk_dp->next_bridge);
2532+
mtk_dp->next_bridge = NULL;
2533+
return ret;
2534+
}
2535+
return 0;
2536+
}
2537+
25042538
static int mtk_dp_probe(struct platform_device *pdev)
25052539
{
25062540
struct mtk_dp *mtk_dp;
@@ -2519,21 +2553,14 @@ static int mtk_dp_probe(struct platform_device *pdev)
25192553
return dev_err_probe(dev, mtk_dp->irq,
25202554
"failed to request dp irq resource\n");
25212555

2522-
mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
2523-
if (IS_ERR(mtk_dp->next_bridge) &&
2524-
PTR_ERR(mtk_dp->next_bridge) == -ENODEV)
2525-
mtk_dp->next_bridge = NULL;
2526-
else if (IS_ERR(mtk_dp->next_bridge))
2527-
return dev_err_probe(dev, PTR_ERR(mtk_dp->next_bridge),
2528-
"Failed to get bridge\n");
2529-
25302556
ret = mtk_dp_dt_parse(mtk_dp, pdev);
25312557
if (ret)
25322558
return dev_err_probe(dev, ret, "Failed to parse dt\n");
25332559

2534-
drm_dp_aux_init(&mtk_dp->aux);
25352560
mtk_dp->aux.name = "aux_mtk_dp";
2561+
mtk_dp->aux.dev = dev;
25362562
mtk_dp->aux.transfer = mtk_dp_aux_transfer;
2563+
drm_dp_aux_init(&mtk_dp->aux);
25372564

25382565
spin_lock_init(&mtk_dp->irq_thread_lock);
25392566

@@ -2577,6 +2604,43 @@ static int mtk_dp_probe(struct platform_device *pdev)
25772604
mtk_dp->need_debounce = true;
25782605
timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0);
25792606

2607+
if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP) {
2608+
/*
2609+
* Set the data lanes to idle in case the bootloader didn't
2610+
* properly close the eDP port to avoid stalls and then
2611+
* reinitialize, reset and power on the AUX block.
2612+
*/
2613+
mtk_dp_set_idle_pattern(mtk_dp, true);
2614+
mtk_dp_initialize_aux_settings(mtk_dp);
2615+
mtk_dp_power_enable(mtk_dp);
2616+
2617+
/*
2618+
* Power on the AUX to allow reading the EDID from aux-bus:
2619+
* please note that it is necessary to call power off in the
2620+
* .done_probing() callback (mtk_dp_edp_link_panel), as only
2621+
* there we can safely assume that we finished reading EDID.
2622+
*/
2623+
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
2624+
DP_PWR_STATE_BANDGAP_TPLL_LANE,
2625+
DP_PWR_STATE_MASK);
2626+
2627+
ret = devm_of_dp_aux_populate_bus(&mtk_dp->aux, mtk_dp_edp_link_panel);
2628+
if (ret) {
2629+
/* -ENODEV this means that the panel is not on the aux-bus */
2630+
if (ret == -ENODEV) {
2631+
ret = mtk_dp_edp_link_panel(&mtk_dp->aux);
2632+
if (ret)
2633+
return ret;
2634+
} else {
2635+
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
2636+
DP_PWR_STATE_BANDGAP_TPLL,
2637+
DP_PWR_STATE_MASK);
2638+
mtk_dp_power_disable(mtk_dp);
2639+
return ret;
2640+
}
2641+
}
2642+
}
2643+
25802644
pm_runtime_enable(dev);
25812645
pm_runtime_get_sync(dev);
25822646

0 commit comments

Comments
 (0)