Skip to content

Commit 7c7b708

Browse files
committed
drm: apple: Add preliminary VRR support
DCP supports VRR/Adaptive Sync, with its enormous firmware blob handling the low-level details for us. Display refresh rate is determined by the swap timing values provided to DCP on each swap request. VRR is activated by setting IOMFBadaptive_sync_parameter::minRR and then requesting a modeset. Wire up all of the required KMS properties to expose VRR to userspace, and tell DCP to enable it when supported. This enables VRR *unconditionally* for supported sinks, which will be fixed in a future commit. Signed-off-by: James Calligeros <[email protected]>
1 parent adf1383 commit 7c7b708

5 files changed

Lines changed: 59 additions & 6 deletions

File tree

drivers/gpu/drm/apple/apple_drv.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ static int apple_probe_per_dcp(struct device *dev,
335335
if (ret)
336336
return ret;
337337

338+
ret = drm_connector_attach_vrr_capable_property(&connector->base);
339+
if (ret)
340+
return ret;
341+
338342
connector->base.polled = DRM_CONNECTOR_POLL_HPD;
339343
connector->connected = false;
340344
connector->dcp = dcp;

drivers/gpu/drm/apple/iomfb.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ void dcp_hotplug(struct work_struct *work)
244244

245245
if (!connector->connected) {
246246
drm_edid_free(connector->drm_edid);
247+
drm_connector_set_vrr_capable_property(&connector->base, false);
247248
connector->drm_edid = NULL;
248249
}
249250

drivers/gpu/drm/apple/iomfb_template.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,8 +546,9 @@ static u8 dcpep_cb_prop_chunk(struct apple_dcp *dcp,
546546
static bool dcpep_process_chunks(struct apple_dcp *dcp,
547547
struct dcp_set_dcpav_prop_end_req *req)
548548
{
549+
struct apple_connector *connector = dcp->connector;
549550
struct dcp_parse_ctx ctx;
550-
int ret;
551+
int ret, i;
551552

552553
if (!dcp->chunks.data) {
553554
dev_warn(dcp->dev, "ignoring spurious end\n");
@@ -589,6 +590,15 @@ static bool dcpep_process_chunks(struct apple_dcp *dcp,
589590
dcp_set_dimensions(dcp);
590591
}
591592

593+
if (connector) {
594+
for (i = 0; i < dcp->nr_modes; i++) {
595+
if (dcp->modes[i].vrr) {
596+
drm_connector_set_vrr_capable_property(&connector->base, true);
597+
break;
598+
}
599+
}
600+
}
601+
592602
return true;
593603
}
594604

@@ -1172,6 +1182,33 @@ static void complete_set_digital_out_mode(struct apple_dcp *dcp, void *data,
11721182
}
11731183
}
11741184

1185+
/* Changes to Adaptive Sync require a trip through set_digital_out_mode */
1186+
static void dcp_on_set_adaptive_sync(struct apple_dcp *dcp, void *out, void *cookie)
1187+
{
1188+
dcp_set_digital_out_mode(dcp, false, &dcp->mode,
1189+
complete_set_digital_out_mode, cookie);
1190+
}
1191+
1192+
static void dcp_set_adaptive_sync(struct apple_dcp *dcp, u64 rate, void *cookie)
1193+
{
1194+
struct dcp_set_parameter_dcp param = {
1195+
.param = IOMFBPARAM_ADAPTIVE_SYNC,
1196+
.value = {
1197+
rate & 0xffffffff, /* minRR */
1198+
0, /* mediaTargetRate */
1199+
0, /* Fractional Rate (?) */
1200+
0, /* unused */
1201+
},
1202+
#if DCP_FW_VER >= DCP_FW_VERSION(13, 2, 0)
1203+
.count = 3,
1204+
#else
1205+
.count = 1,
1206+
#endif
1207+
};
1208+
1209+
dcp_set_parameter_dcp(dcp, false, &param, dcp_on_set_adaptive_sync, cookie);
1210+
}
1211+
11751212
int DCP_FW_NAME(iomfb_modeset)(struct apple_dcp *dcp,
11761213
struct drm_crtc_state *crtc_state)
11771214
{
@@ -1226,8 +1263,11 @@ int DCP_FW_NAME(iomfb_modeset)(struct apple_dcp *dcp,
12261263

12271264
dcp->during_modeset = true;
12281265

1229-
dcp_set_digital_out_mode(dcp, false, &dcp->mode,
1230-
complete_set_digital_out_mode, cookie);
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);
12311271

12321272
/*
12331273
* The DCP firmware has an internal timeout of ~8 seconds for

drivers/gpu/drm/apple/parser.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,10 @@ static int parse_mode(struct dcp_parse_ctx *handle,
454454
ret = parse_dimension(it.handle, &horiz);
455455
else if (!strcmp(key, "VerticalAttributes"))
456456
ret = parse_dimension(it.handle, &vert);
457+
else if (!strcmp(key, "MinimumVariableRefreshRate"))
458+
ret = parse_int(it.handle, &out->min_vrr);
459+
else if (!strcmp(key, "MaximumVariableRefreshRate"))
460+
ret = parse_int(it.handle, &out->max_vrr);
457461
else if (!strcmp(key, "ColorModes"))
458462
ret = parse_color_modes(it.handle, out);
459463
else if (!strcmp(key, "ID"))
@@ -502,15 +506,17 @@ static int parse_mode(struct dcp_parse_ctx *handle,
502506
/*
503507
* HACK:
504508
* Mark the 120 Hz mode on j314/j316 (identified by resolution) as vrr.
505-
* We still do not know how to drive VRR but at least seetinng timestamps
506-
* in the the swap_surface message to non-zero values drives the display
507-
* at 120 fps.
509+
* Setting timestamps in the the swap_surface message to non-zero
510+
* values drives the display at 120 fps.
508511
*/
509512
if (vert.precise_sync_rate >> 16 == 120 &&
510513
((horiz.active == 3024 && vert.active == 1964) ||
511514
(horiz.active == 3456 && vert.active == 2234)))
512515
out->vrr = true;
513516

517+
if (out->min_vrr && out->max_vrr)
518+
out->vrr = true;
519+
514520
vert.active -= notch_height;
515521
vert.sync_width += notch_height;
516522

drivers/gpu/drm/apple/parser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ struct dcp_display_mode {
9292
struct dcp_color_mode sdr;
9393
struct dcp_color_mode best;
9494
bool vrr;
95+
s64 min_vrr;
96+
s64 max_vrr;
9597
};
9698

9799
struct dimension {

0 commit comments

Comments
 (0)