Skip to content

Commit 09fb993

Browse files
committed
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 <j@jannau.net>
1 parent d962807 commit 09fb993

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>
@@ -444,7 +445,10 @@ static int apple_drm_init_dcp(struct device *dev)
444445
if (num_dcp < 1)
445446
return -ENODEV;
446447

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

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

463469
return 0;
464470
}

drivers/gpu/drm/apple/dcp.c

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

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

366383
ret = iomfb_start_rtkit(dcp);
367384
if (ret)
@@ -373,17 +390,8 @@ EXPORT_SYMBOL(dcp_start);
373390

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

388396
return 0;
389397
}

0 commit comments

Comments
 (0)