Skip to content

Commit a34ed04

Browse files
committed
drm: apple: Use delayed work for debounced oob HPD
When connecting too quickly the USB Type-C controller signals HPD disconnect resulting in a time consuming connect/disconnect/connect sequence. Instead defer the connect for 2 seconds. Usually a second HPD arrives on which we can start the connect on DCP level immediately (currently the timer is reduced to 100ms, which is probably not needed). Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 91073dc commit a34ed04

2 files changed

Lines changed: 79 additions & 14 deletions

File tree

drivers/gpu/drm/apple/dcp-internal.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ struct apple_dcp_hw_data {
112112
u32 num_dptx_ports;
113113
};
114114

115+
enum dcp_hdp_state {
116+
DCP_HPD_UNKNOWN,
117+
DCP_HPD_OOB_CONNECTED,
118+
DCP_HPD_OOB_DISCONNECTED,
119+
};
120+
115121
/* TODO: move IOMFB members to its own struct */
116122
struct apple_dcp {
117123
struct device *dev;
@@ -257,6 +263,12 @@ struct apple_dcp {
257263
struct gpio_desc *dp2hdmi_pwren;
258264

259265
struct mutex hpd_mutex;
266+
struct mutex hpd_deferred_mutex;
267+
struct delayed_work hpd_wq;
268+
struct {
269+
enum dcp_hdp_state state;
270+
u32 port;
271+
} hpd;
260272

261273
u32 dptx_phy;
262274
u32 dptx_die;

drivers/gpu/drm/apple/dcp.c

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ int dcp_get_connector_type(struct platform_device *pdev)
370370
}
371371
EXPORT_SYMBOL_GPL(dcp_get_connector_type);
372372

373-
#define DPTX_CONNECT_TIMEOUT msecs_to_jiffies(1000)
373+
#define DPTX_CONNECT_TIMEOUT msecs_to_jiffies(2000)
374374

375375
static int dcp_dptx_connect(struct apple_dcp *dcp, u32 port)
376376
{
@@ -410,24 +410,16 @@ static int dcp_dptx_connect(struct apple_dcp *dcp, u32 port)
410410

411411
usleep_range(5, 10);
412412

413+
if (dcp->connector_type == DRM_MODE_CONNECTOR_DisplayPort)
414+
dptxport_set_hpd(dcp->dptxport[port].service, true);
415+
413416
return 0;
414417

415418
out_unlock:
416419
mutex_unlock(&dcp->hpd_mutex);
417420
return ret;
418421
}
419422

420-
int dcp_dptx_connect_oob(struct platform_device *pdev, u32 port)
421-
{
422-
struct apple_dcp *dcp = platform_get_drvdata(pdev);
423-
int err = dcp_dptx_connect(dcp, port);
424-
if (err < 0)
425-
return err;
426-
dptxport_set_hpd(dcp->dptxport[port].service, true);
427-
return 0;
428-
}
429-
EXPORT_SYMBOL_GPL(dcp_dptx_connect_oob);
430-
431423
static int dcp_dptx_disconnect(struct apple_dcp *dcp, u32 port)
432424
{
433425
dev_info(dcp->dev, "%s(port=%d)\n", __func__, port);
@@ -442,11 +434,69 @@ static int dcp_dptx_disconnect(struct apple_dcp *dcp, u32 port)
442434
return 0;
443435
}
444436

437+
static void dcp_deferred_hpd_work(struct work_struct *work)
438+
{
439+
struct apple_dcp *dcp = container_of(to_delayed_work(work), struct apple_dcp, hpd_wq);
440+
int err;
441+
442+
guard(mutex)(&dcp->hpd_deferred_mutex);
443+
dev_info(dcp->dev, "%s\n", __func__);
444+
445+
switch (dcp->hpd.state) {
446+
case DCP_HPD_OOB_CONNECTED:
447+
err = dcp_dptx_connect(dcp, dcp->hpd.port);
448+
if (err < 0)
449+
dev_warn(dcp->dev, "OOB HPD connect failed:%d\n", err);
450+
break;
451+
case DCP_HPD_OOB_DISCONNECTED:
452+
dptxport_set_hpd(dcp->dptxport[dcp->hpd.port].service, false);
453+
err = dcp_dptx_disconnect(dcp, dcp->hpd.port);
454+
if (err < 0)
455+
dev_warn(dcp->dev, "OOB HPD disconnect failed:%d\n", err);
456+
break;
457+
default:
458+
return;
459+
}
460+
}
461+
462+
static int dcp_dptx_schedule_hdp_work(struct apple_dcp *dcp,
463+
enum dcp_hdp_state state, u32 port)
464+
{
465+
guard(mutex)(&dcp->hpd_deferred_mutex);
466+
dcp->hpd.port = port;
467+
dcp->hpd.state = state;
468+
469+
if (state == DCP_HPD_OOB_CONNECTED)
470+
{
471+
guard(mutex)(&dcp->hpd_mutex);
472+
if (dcp->dptxport[port].connected)
473+
return 0;
474+
475+
if (delayed_work_pending(&dcp->hpd_wq))
476+
timer_reduce(&dcp->hpd_wq.timer, msecs_to_jiffies(100));
477+
else
478+
schedule_delayed_work(&dcp->hpd_wq, msecs_to_jiffies(2000));
479+
} else {
480+
if (!delayed_work_pending(&dcp->hpd_wq))
481+
schedule_delayed_work(&dcp->hpd_wq, msecs_to_jiffies(25));
482+
}
483+
484+
return 0;
485+
}
486+
487+
int dcp_dptx_connect_oob(struct platform_device *pdev, u32 port)
488+
{
489+
struct apple_dcp *dcp = platform_get_drvdata(pdev);
490+
491+
return dcp_dptx_schedule_hdp_work(dcp, DCP_HPD_OOB_CONNECTED, port);
492+
}
493+
EXPORT_SYMBOL_GPL(dcp_dptx_connect_oob);
494+
445495
int dcp_dptx_disconnect_oob(struct platform_device *pdev, u32 port)
446496
{
447497
struct apple_dcp *dcp = platform_get_drvdata(pdev);
448-
dptxport_set_hpd(dcp->dptxport[port].service, false);
449-
return dcp_dptx_disconnect(dcp, port);
498+
499+
return dcp_dptx_schedule_hdp_work(dcp, DCP_HPD_OOB_DISCONNECTED, port);
450500
}
451501
EXPORT_SYMBOL_GPL(dcp_dptx_disconnect_oob);
452502

@@ -971,6 +1021,8 @@ static int dcp_comp_bind(struct device *dev, struct device *main, void *data)
9711021
dev_info(dev, "DCP index:%u dptx target phy: %u dptx die: %u\n",
9721022
dcp->index, dcp->dptx_phy, dcp->dptx_die);
9731023
mutex_init(&dcp->hpd_mutex);
1024+
mutex_init(&dcp->hpd_deferred_mutex);
1025+
INIT_DELAYED_WORK(&dcp->hpd_wq, dcp_deferred_hpd_work);
9741026

9751027
if (!show_notch)
9761028
ret = of_property_read_u32(dev->of_node, "apple,notch-height",
@@ -1114,6 +1166,7 @@ static void dcp_comp_unbind(struct device *dev, struct device *main, void *data)
11141166
cancel_work_sync(&dcp->bl_update_wq);
11151167
}
11161168
cancel_work_sync(&dcp->vblank_wq);
1169+
cancel_delayed_work_sync(&dcp->hpd_wq);
11171170

11181171
devm_clk_put(dev, dcp->clk);
11191172
dcp->clk = NULL;

0 commit comments

Comments
 (0)