Skip to content

Commit 8eb2787

Browse files
committed
drm: apple: Trigger set_digital_out_mode when minRR is changed
DCP requires a "mode change" to be triggered when changing the minRR property of the IOMFBParameter_adaptive_sync parameter set. Additionally, the setting of the parameter set must be fenced by a wait cookie, or DCP will crash. We cannot trigger a "full" modeset with iomfb_modeset as that function has failure conditions. iomfb_flush must never fail. iomfb_modeset also has a very large timeout. Luckily for us, toggling VRR on and off does not actually trigger a full modeset on the connected sink when calling set_digital_out_mode. It is therefore safe to set the parameter and trigger set_digital_out_mode directly from iomfb_flush. If this for some reason times out, just fire a vblank and return gracefully. Signed-off-by: James Calligeros <[email protected]> squash into force modeset Signed-off-by: James Calligeros <[email protected]>
1 parent 049e881 commit 8eb2787

2 files changed

Lines changed: 42 additions & 5 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ struct apple_dcp {
186186
bool during_modeset;
187187
bool valid_mode;
188188
bool use_timestamps;
189+
bool vrr_enabled;
190+
s64 min_vrr;
189191
struct dcp_set_digital_out_mode_req mode;
190192

191193
/* completion for active turning true */

drivers/gpu/drm/apple/iomfb_template.c

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,11 @@ int DCP_FW_NAME(iomfb_modeset)(struct apple_dcp *dcp,
12511251
/* Keep track of suspected vrr modes */
12521252
dcp->use_timestamps = mode->vrr;
12531253

1254+
if (mode->vrr)
1255+
dcp->min_vrr = mode->min_vrr;
1256+
else
1257+
dcp->min_vrr = 0;
1258+
12541259
cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
12551260
if (!cookie) {
12561261
return -ENOMEM;
@@ -1263,11 +1268,8 @@ int DCP_FW_NAME(iomfb_modeset)(struct apple_dcp *dcp,
12631268

12641269
dcp->during_modeset = true;
12651270

1266-
if (mode->vrr)
1267-
dcp_set_adaptive_sync(dcp, mode->min_vrr, cookie);
1268-
else
1269-
dcp_set_digital_out_mode(dcp, false, &dcp->mode,
1270-
complete_set_digital_out_mode, cookie);
1271+
dcp_set_digital_out_mode(dcp, false, &dcp->mode,
1272+
complete_set_digital_out_mode, cookie);
12711273

12721274
/*
12731275
* The DCP firmware has an internal timeout of ~8 seconds for
@@ -1434,6 +1436,39 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru
14341436
dcp->brightness.update = false;
14351437
}
14361438

1439+
/*
1440+
* If VRR is requested, we need to set the minRR parameter
1441+
* and then call set_digital_out_mode. This does *not* trigger
1442+
* a full modeset.
1443+
*/
1444+
if (crtc_state->vrr_enabled != dcp->vrr_enabled) {
1445+
struct dcp_wait_cookie *cookie;
1446+
int timeout;
1447+
1448+
cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
1449+
if (!cookie) {
1450+
schedule_work(&dcp->vblank_wq);
1451+
return;
1452+
}
1453+
1454+
init_completion(&cookie->done);
1455+
kref_init(&cookie->refcount);
1456+
kref_get(&cookie->refcount);
1457+
1458+
dcp_set_adaptive_sync(dcp, crtc_state->vrr_enabled ? dcp->min_vrr : 0, cookie);
1459+
1460+
timeout = wait_for_completion_timeout(&cookie->done,
1461+
msecs_to_jiffies(500));
1462+
if (!timeout) {
1463+
schedule_work(&dcp->vblank_wq);
1464+
return;
1465+
}
1466+
1467+
kref_put(&cookie->refcount, release_wait_cookie);
1468+
1469+
dcp->vrr_enabled = crtc_state->vrr_enabled;
1470+
}
1471+
14371472
if (crtc_state->color_mgmt_changed) {
14381473
struct iomfb_set_matrix_req mat = {
14391474
.location = 9,

0 commit comments

Comments
 (0)