Skip to content

Commit 2a6c77d

Browse files
jannaumarcan
authored andcommitted
drm: apple: Adjust startup sequence and timing for dptx
DPTX setup from an initialized connection and display with sleeping and reset dcp is unfortunately quite fragile. The display connection has to be stopped and reestablished. Goodbye flicker free boot. If the IOMFB endpoint is started too early dcp might provide incomplete timing modes which prevent modesets. On display standby a HPD is triggered should result in a fully initialized dcp. If not a display cable unplug and plug should help. MacOS doesn't handle this at all and just gives up. Signed-off-by: Janne Grunau <[email protected]>
1 parent 741b581 commit 2a6c77d

2 files changed

Lines changed: 43 additions & 29 deletions

File tree

drivers/gpu/drm/apple/apple_drv.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
#include <linux/component.h>
11+
#include <linux/delay.h>
1112
#include <linux/dma-mapping.h>
1213
#include <linux/jiffies.h>
1314
#include <linux/module.h>
@@ -443,7 +444,10 @@ static int apple_drm_init_dcp(struct device *dev)
443444
if (num_dcp < 1)
444445
return -ENODEV;
445446

446-
timeout = get_jiffies_64() + msecs_to_jiffies(500);
447+
/*
448+
* Starting DPTX might take some time.
449+
*/
450+
timeout = get_jiffies_64() + msecs_to_jiffies(3000);
447451

448452
for (i = 0; i < num_dcp; ++i) {
449453
u64 jiffies = get_jiffies_64();
@@ -458,6 +462,8 @@ static int apple_drm_init_dcp(struct device *dev)
458462
if (ret)
459463
dev_warn(dev, "DCP[%d] not ready: %d\n", i, ret);
460464
}
465+
/* HACK: Wait for dcp* to settle before a modeset */
466+
msleep(100);
461467

462468
return 0;
463469
}

drivers/gpu/drm/apple/dcp.c

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -346,23 +346,40 @@ int dcp_start(struct platform_device *pdev)
346346
if (ret)
347347
dev_warn(dcp->dev, "Failed to start system endpoint: %d", ret);
348348

349-
if (dcp->phy) {
350-
if (dcp->fw_compat >= DCP_FIRMWARE_V_13_5) {
351-
ret = ibootep_init(dcp);
352-
if (ret)
353-
dev_warn(dcp->dev,
354-
"Failed to start IBOOT endpoint: %d",
355-
ret);
356-
357-
ret = dptxep_init(dcp);
358-
if (ret)
359-
dev_warn(dcp->dev,
360-
"Failed to start DPTX endpoint: %d",
361-
ret);
362-
} else
363-
dev_warn(dcp->dev,
364-
"OS firmware incompatible with dptxport EP\n");
365-
}
349+
if (dcp->phy && dcp->fw_compat >= DCP_FIRMWARE_V_13_5) {
350+
ret = ibootep_init(dcp);
351+
if (ret)
352+
dev_warn(dcp->dev, "Failed to start IBOOT endpoint: %d",
353+
ret);
354+
355+
ret = dptxep_init(dcp);
356+
if (ret)
357+
dev_warn(dcp->dev, "Failed to start DPTX endpoint: %d",
358+
ret);
359+
else if (dcp->dptxport[0].enabled) {
360+
bool connected;
361+
/* force disconnect on start - necessary if the display
362+
* is already up from m1n1
363+
*/
364+
dptxport_set_hpd(dcp->dptxport[0].service, false);
365+
dptxport_release_display(dcp->dptxport[0].service);
366+
usleep_range(10 * USEC_PER_MSEC, 25 * USEC_PER_MSEC);
367+
368+
connected = gpiod_get_value_cansleep(dcp->hdmi_hpd);
369+
dev_info(dcp->dev, "%s: DP2HDMI HPD connected:%d\n", __func__, connected);
370+
371+
// necessary on j473/j474 but not on j314c
372+
if (connected)
373+
dcp_dptx_connect(dcp, 0);
374+
/*
375+
* Long sleep necessary to ensure dcp delivers timing
376+
* modes with matched color modes.
377+
* 400ms was sufficient on j473
378+
*/
379+
msleep(500);
380+
}
381+
} else if (dcp->phy)
382+
dev_warn(dcp->dev, "OS firmware incompatible with dptxport EP\n");
366383

367384
ret = iomfb_start_rtkit(dcp);
368385
if (ret)
@@ -374,17 +391,8 @@ EXPORT_SYMBOL(dcp_start);
374391

375392
static int dcp_enable_dp2hdmi_hpd(struct apple_dcp *dcp)
376393
{
377-
if (dcp->hdmi_hpd) {
378-
bool connected = gpiod_get_value_cansleep(dcp->hdmi_hpd);
379-
dev_info(dcp->dev, "%s: DP2HDMI HPD connected:%d\n", __func__, connected);
380-
381-
// necessary on j473/j474 but not on j314c
382-
if (connected)
383-
dcp_dptx_connect(dcp, 0);
384-
385-
if (dcp->hdmi_hpd_irq)
386-
enable_irq(dcp->hdmi_hpd_irq);
387-
}
394+
if (dcp->hdmi_hpd_irq)
395+
enable_irq(dcp->hdmi_hpd_irq);
388396

389397
return 0;
390398
}

0 commit comments

Comments
 (0)