Skip to content

Commit 8997bef

Browse files
jannaumarcan
authored andcommitted
drm: apple: Prefer RGB SDR modes
DCP color mode scoring seems to prefer high bit depth color modes even when it it would require DSC. For example 12-bit 4k 60 Hz YCbCr 4:4:4 over a 600 MHz HDMI 2.0 link. Prefer 8-/10-bit RGB or YCbCr 4:4:4 modes if available. Signed-off-by: Janne Grunau <[email protected]>
1 parent 1d26b13 commit 8997bef

3 files changed

Lines changed: 138 additions & 24 deletions

File tree

drivers/gpu/drm/apple/iomfb_template.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,7 @@ int DCP_FW_NAME(iomfb_modeset)(struct apple_dcp *dcp,
11921192
{
11931193
struct dcp_display_mode *mode;
11941194
struct dcp_wait_cookie *cookie;
1195+
struct dcp_color_mode *cmode = NULL;
11951196
int ret;
11961197

11971198
mode = lookup_mode(dcp, &crtc_state->mode);
@@ -1205,6 +1206,21 @@ int DCP_FW_NAME(iomfb_modeset)(struct apple_dcp *dcp,
12051206
"set_digital_out_mode(color:%d timing:%d) " DRM_MODE_FMT "\n",
12061207
mode->color_mode_id, mode->timing_mode_id,
12071208
DRM_MODE_ARG(&crtc_state->mode));
1209+
if (mode->color_mode_id == mode->sdr_rgb.id)
1210+
cmode = &mode->sdr_rgb;
1211+
else if (mode->color_mode_id == mode->sdr_444.id)
1212+
cmode = &mode->sdr_444;
1213+
else if (mode->color_mode_id == mode->sdr.id)
1214+
cmode = &mode->sdr;
1215+
else if (mode->color_mode_id == mode->best.id)
1216+
cmode = &mode->best;
1217+
if (cmode)
1218+
dev_info(dcp->dev,
1219+
"set_digital_out_mode() color mode depth:%hhu format:%u "
1220+
"colorimetry:%u eotf:%u range:%u\n", cmode->depth,
1221+
cmode->format, cmode->colorimetry, cmode->eotf,
1222+
cmode->range);
1223+
12081224
dcp->mode = (struct dcp_set_digital_out_mode_req){
12091225
.color_mode_id = mode->color_mode_id,
12101226
.timing_mode_id = mode->timing_mode_id

drivers/gpu/drm/apple/parser.c

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,42 @@ struct color_mode {
313313
s64 score;
314314
};
315315

316-
static int parse_color_modes(struct dcp_parse_ctx *handle, s64 *preferred_id)
316+
static int fill_color_mode(struct dcp_color_mode *color,
317+
struct color_mode *cmode)
318+
{
319+
if (color->score >= cmode->score)
320+
return 0;
321+
322+
if (cmode->colorimetry < 0 || cmode->colorimetry >= DCP_COLORIMETRY_COUNT)
323+
return -EINVAL;
324+
if (cmode->depth < 8 || cmode->depth > 12)
325+
return -EINVAL;
326+
if (cmode->dynamic_range < 0 || cmode->dynamic_range >= DCP_COLOR_YCBCR_RANGE_COUNT)
327+
return -EINVAL;
328+
if (cmode->eotf < 0 || cmode->eotf >= DCP_EOTF_COUNT)
329+
return -EINVAL;
330+
if (cmode->pixel_encoding < 0 || cmode->pixel_encoding >= DCP_COLOR_FORMAT_COUNT)
331+
return -EINVAL;
332+
333+
color->score = cmode->score;
334+
color->id = cmode->id;
335+
color->eotf = cmode->eotf;
336+
color->format = cmode->pixel_encoding;
337+
color->colorimetry = cmode->colorimetry;
338+
color->range = cmode->dynamic_range;
339+
color->depth = cmode->depth;
340+
341+
return 0;
342+
}
343+
344+
static int parse_color_modes(struct dcp_parse_ctx *handle,
345+
struct dcp_display_mode *out)
317346
{
318347
struct iterator outer_it;
319348
int ret = 0;
320-
s64 best_score = -1, best_score_sdr = -1;
321-
s64 best_id = -1, best_id_sdr = -1;
322-
323-
*preferred_id = -1;
349+
out->sdr_444.score = -1;
350+
out->sdr_rgb.score = -1;
351+
out->best.score = -1;
324352

325353
dcp_parse_foreach_in_array(handle, outer_it) {
326354
struct iterator it;
@@ -367,25 +395,18 @@ static int parse_color_modes(struct dcp_parse_ctx *handle, s64 *preferred_id)
367395
cmode.eotf, cmode.dynamic_range,
368396
cmode.pixel_encoding);
369397

370-
if (cmode.eotf == 0) {
371-
if (cmode.score > best_score_sdr) {
372-
best_score_sdr = cmode.score;
373-
best_id_sdr = cmode.id;
374-
}
375-
} else {
376-
if (cmode.score > best_score) {
377-
best_score = cmode.score;
378-
best_id = cmode.id;
379-
}
398+
if (cmode.eotf == DCP_EOTF_SDR_GAMMA) {
399+
if (cmode.pixel_encoding == DCP_COLOR_FORMAT_RGB &&
400+
cmode.depth <= 10)
401+
fill_color_mode(&out->sdr_rgb, &cmode);
402+
else if (cmode.pixel_encoding == DCP_COLOR_FORMAT_YCBCR444 &&
403+
cmode.depth <= 10)
404+
fill_color_mode(&out->sdr_444, &cmode);
405+
fill_color_mode(&out->sdr, &cmode);
380406
}
407+
fill_color_mode(&out->best, &cmode);
381408
}
382409

383-
/* prefer SDR color modes as long as HDR is not supported */
384-
if (best_score_sdr >= 0)
385-
*preferred_id = best_id_sdr;
386-
else if (best_score >= 0)
387-
*preferred_id = best_id;
388-
389410
return 0;
390411
}
391412

@@ -427,7 +448,7 @@ static int parse_mode(struct dcp_parse_ctx *handle,
427448
else if (!strcmp(key, "VerticalAttributes"))
428449
ret = parse_dimension(it.handle, &vert);
429450
else if (!strcmp(key, "ColorModes"))
430-
ret = parse_color_modes(it.handle, &best_color_mode);
451+
ret = parse_color_modes(it.handle, out);
431452
else if (!strcmp(key, "ID"))
432453
ret = parse_int(it.handle, &id);
433454
else if (!strcmp(key, "IsVirtual"))
@@ -445,8 +466,17 @@ static int parse_mode(struct dcp_parse_ctx *handle,
445466
return ret;
446467
}
447468
}
448-
449-
trace_iomfb_parse_mode_success(id, &horiz, &vert, best_color_mode, is_virtual, *score);
469+
if (out->sdr_rgb.score >= 0)
470+
best_color_mode = out->sdr_rgb.id;
471+
else if (out->sdr_444.score >= 0)
472+
best_color_mode = out->sdr_444.id;
473+
else if (out->sdr.score >= 0)
474+
best_color_mode = out->sdr.id;
475+
else if (out->best.score >= 0)
476+
best_color_mode = out->best.id;
477+
478+
trace_iomfb_parse_mode_success(id, &horiz, &vert, best_color_mode,
479+
is_virtual, *score);
450480

451481
/*
452482
* Reject modes without valid color mode.

drivers/gpu/drm/apple/parser.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,70 @@ struct dcp_parse_ctx {
1515
u32 pos, len;
1616
};
1717

18+
enum dcp_color_eotf {
19+
DCP_EOTF_SDR_GAMMA = 0, // "SDR gamma"
20+
DCP_EOTF_HDR_GAMMA = 1, // "HDR gamma"
21+
DCP_EOTF_ST_2084 = 2, // "ST 2084 (PQ)"
22+
DCP_EOTF_BT_2100 = 3, // "BT.2100 (HLG)"
23+
DCP_EOTF_COUNT
24+
};
25+
26+
enum dcp_color_format {
27+
DCP_COLOR_FORMAT_RGB = 0, // "RGB"
28+
DCP_COLOR_FORMAT_YCBCR420 = 1, // "YUV 4:2:0"
29+
DCP_COLOR_FORMAT_YCBCR422 = 3, // "YUV 4:2:2"
30+
DCP_COLOR_FORMAT_YCBCR444 = 2, // "YUV 4:4:4"
31+
DCP_COLOR_FORMAT_DV_NATIVE = 4, // "DolbyVision (native)"
32+
DCP_COLOR_FORMAT_DV_HDMI = 5, // "DolbyVision (HDMI)"
33+
DCP_COLOR_FORMAT_YCBCR422_DP = 6, // "YCbCr 4:2:2 (DP tunnel)"
34+
DCP_COLOR_FORMAT_YCBCR422_HDMI = 7, // "YCbCr 4:2:2 (HDMI tunnel)"
35+
DCP_COLOR_FORMAT_DV_LL_YCBCR422 = 8, // "DolbyVision LL YCbCr 4:2:2"
36+
DCP_COLOR_FORMAT_DV_LL_YCBCR422_DP = 9, // "DolbyVision LL YCbCr 4:2:2 (DP)"
37+
DCP_COLOR_FORMAT_DV_LL_YCBCR422_HDMI = 10, // "DolbyVision LL YCbCr 4:2:2 (HDMI)"
38+
DCP_COLOR_FORMAT_DV_LL_YCBCR444 = 11, // "DolbyVision LL YCbCr 4:4:4"
39+
DCP_COLOR_FORMAT_DV_LL_RGB422 = 12, // "DolbyVision LL RGB 4:2:2"
40+
DCP_COLOR_FORMAT_GRGB_BLUE_422 = 13, // "GRGB as YCbCr422 (Even line blue)"
41+
DCP_COLOR_FORMAT_GRGB_RED_422 = 14, // "GRGB as YCbCr422 (Even line red)"
42+
DCP_COLOR_FORMAT_COUNT
43+
};
44+
45+
enum dcp_colorimetry {
46+
DCP_COLORIMETRY_BT601 = 0, // "SMPTE 170M/BT.601"
47+
DCP_COLORIMETRY_BT709 = 1, // "BT.701"
48+
DCP_COLORIMETRY_XVYCC_601 = 2, // "xvYCC601"
49+
DCP_COLORIMETRY_XVYCC_709 = 3, // "xvYCC709"
50+
DCP_COLORIMETRY_SYCC_601 = 4, // "sYCC601"
51+
DCP_COLORIMETRY_ADOBE_YCC_601 = 5, // "AdobeYCC601"
52+
DCP_COLORIMETRY_BT2020_CYCC = 6, // "BT.2020 (c)"
53+
DCP_COLORIMETRY_BT2020_YCC = 7, // "BT.2020 (nc)"
54+
DCP_COLORIMETRY_VSVDB = 8, // "DolbyVision VSVDB"
55+
DCP_COLORIMETRY_BT2020_RGB = 9, // "BT.2020 (RGB)"
56+
DCP_COLORIMETRY_SRGB = 10, // "sRGB"
57+
DCP_COLORIMETRY_SCRGB = 11, // "scRGB"
58+
DCP_COLORIMETRY_SCRGB_FIXED = 12, // "scRGBfixed"
59+
DCP_COLORIMETRY_ADOBE_RGB = 13, // "AdobeRGB"
60+
DCP_COLORIMETRY_DCI_P3_RGB_D65 = 14, // "DCI-P3 (D65)"
61+
DCP_COLORIMETRY_DCI_P3_RGB_THEATER = 15, // "DCI-P3 (Theater)"
62+
DCP_COLORIMETRY_RGB = 16, // "Default RGB"
63+
DCP_COLORIMETRY_COUNT
64+
};
65+
66+
enum dcp_color_range {
67+
DCP_COLOR_YCBCR_RANGE_FULL = 0,
68+
DCP_COLOR_YCBCR_RANGE_LIMITED = 1,
69+
DCP_COLOR_YCBCR_RANGE_COUNT
70+
};
71+
72+
struct dcp_color_mode {
73+
s64 score;
74+
u32 id;
75+
enum dcp_color_eotf eotf;
76+
enum dcp_color_format format;
77+
enum dcp_colorimetry colorimetry;
78+
enum dcp_color_range range;
79+
u8 depth;
80+
};
81+
1882
/*
1983
* Represents a single display mode. These mode objects are populated at
2084
* runtime based on the TimingElements dictionary sent by the DCP.
@@ -23,6 +87,10 @@ struct dcp_display_mode {
2387
struct drm_display_mode mode;
2488
u32 color_mode_id;
2589
u32 timing_mode_id;
90+
struct dcp_color_mode sdr_rgb;
91+
struct dcp_color_mode sdr_444;
92+
struct dcp_color_mode sdr;
93+
struct dcp_color_mode best;
2694
};
2795

2896
struct dimension {

0 commit comments

Comments
 (0)