Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions drivers/gpu/drm/apple/apple_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,19 @@ static int apple_probe_per_dcp(struct device *dev,
crtc->dcp = dcp;
dcp_link(dcp, crtc, connector);

// gnome wants to see BT2020_RGB
u32 supported_colorspaces =
BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
BIT(DRM_MODE_COLORIMETRY_BT2020_RGB);

// allow userspace to signal the color space used
if (!drm_mode_create_dp_colorspace_property(&connector->base, supported_colorspaces))
drm_connector_attach_colorspace_property(&connector->base);

// allow userspace to expose hdr output metadata.
// this indicates "hey i am rendering hdr content now"
drm_connector_attach_hdr_output_metadata_property(&connector->base);

return drm_connector_attach_encoder(&connector->base, &enc->base);
}

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/apple/dcp-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ struct dcp_brightness {
struct backlight_device *bl_dev;
u32 maximum;
u32 dac;
u32 dac_hdr_restore;
int nits;
int scale;
bool update;
Expand Down
13 changes: 13 additions & 0 deletions drivers/gpu/drm/apple/dcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ static bool unstable_edid = true;
module_param(unstable_edid, bool, 0644);
MODULE_PARM_DESC(unstable_edid, "Enable unstable EDID retrival support");

u32 swap_hdr_colorspace = DCP_COLORSPACE_BG_BT2020;
module_param(swap_hdr_colorspace, uint, 0644);
MODULE_PARM_DESC(swap_hdr_colorspace, "Colorspace to use for primary swap with hdr");

u32 swap_hdr_transferfunc = DCP_XFER_FUNC_HDR;
module_param(swap_hdr_transferfunc, uint, 0644);
MODULE_PARM_DESC(swap_hdr_transferfunc, "Transfer function to use for primary swap with hdr");

u32 swap_hdr_brightness = 0x98FFFFC0; // max brightness observed with hdr content
module_param(swap_hdr_brightness, uint, 0644);
MODULE_PARM_DESC(swap_hdr_brightness, "Force the display into this brightness when in hdr mode");


/* copied and simplified from drm_vblank.c */
static void send_vblank_event(struct drm_device *dev,
struct drm_pending_vblank_event *e,
Expand Down
54 changes: 52 additions & 2 deletions drivers/gpu/drm/apple/iomfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,22 @@ struct dcp_rect drm_to_dcp_rect(struct drm_rect *rect)
.h = drm_rect_height(rect) };
}

u32 drm_format_to_dcp(u32 drm)
u32 rgb2101010_dcp_format = fourcc_code('r', '0', '1', 'l');
module_param(rgb2101010_dcp_format, uint, 0644);
MODULE_PARM_DESC(rgb2101010_dcp_format, "dcp color format for DRM_FORMAT_XRGB2101010 in hdr");

u32 drm_format_to_dcp_hdr(u32 drm)
{
switch (drm) {
case DRM_FORMAT_XRGB2101010:
return rgb2101010_dcp_format;
}

pr_warn("DRM format %X not supported in DCP with HDR\n", drm);
return 0;
}

u32 drm_format_to_dcp_sdr(u32 drm)
{
switch (drm) {
case DRM_FORMAT_XRGB8888:
Expand All @@ -372,7 +387,7 @@ u32 drm_format_to_dcp(u32 drm)
return fourcc_code('r', '0', '3', 'w');
}

pr_warn("DRM format %X not supported in DCP\n", drm);
pr_warn("DRM format %X not supported in DCP with SDR\n", drm);
return 0;
}

Expand Down Expand Up @@ -408,6 +423,41 @@ int dcp_get_modes(struct drm_connector *connector)
apple_connector->drm_edid = edid;
}
}

if (!apple_connector->drm_edid && dcp->nr_modes && dcp_has_panel(dcp)) {
// HACK: fake some edid entry for the iinternal panel. This value here is actually for a
// totally different screen, but it has the hdr property set. that property is required
// for gnome and kde to display the "enable hdr" toggle.
static const u8 edidbuf[] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x34, 0xa9, 0x1c, 0xd1,
0x01, 0x01, 0x01, 0x01, 0x00, 0x19, 0x01, 0x03, 0x80, 0xdd, 0x7d, 0x78,
0x0a, 0x06, 0x12, 0xaf, 0x51, 0x4e, 0xad, 0x24, 0x0b, 0x4c, 0x51, 0x20,
0x08, 0x00, 0xa9, 0xc0, 0xa9, 0x40, 0x90, 0x40, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0xe8, 0x00, 0x30, 0xf2, 0x70,
0x5a, 0x80, 0xb0, 0x58, 0x8a, 0x00, 0x1c, 0x00, 0x74, 0x00, 0x00, 0x1e,
0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00,
0x1c, 0x00, 0x74, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45,
0x54, 0x2d, 0x4d, 0x44, 0x4e, 0x48, 0x4d, 0x31, 0x30, 0x0a, 0x20, 0x20,
0x00, 0x00, 0x00, 0xfd, 0x00, 0x17, 0x79, 0x0f, 0x96, 0x3c, 0x00, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x75, 0x02, 0x03, 0x41, 0xb1,
0x57, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x66, 0x65, 0x64, 0x63, 0x62, 0x3f,
0x10, 0x1f, 0x05, 0x14, 0x22, 0x21, 0x20, 0x04, 0x13, 0x02, 0x11, 0x01,
0xe3, 0x05, 0xe0, 0x00, 0x6e, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x38, 0x3c,
0x20, 0x08, 0x80, 0x01, 0x02, 0x03, 0x04, 0x67, 0xd8, 0x5d, 0xc4, 0x01,
0x78, 0x80, 0x03, 0xe2, 0x00, 0xff, 0xe2, 0x0f, 0x63, 0xe3, 0x06, 0x0d,
0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, 0x23, 0x40, 0x30, 0x20, 0x36,
0x00, 0x66, 0x00, 0x64, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x5a
};

pr_info("injecting fake edid buf\n");
const struct drm_edid *edid = drm_edid_alloc(edidbuf, sizeof(edidbuf));
drm_connector_update_edid_property(&dcp->connector->base, drm_edid_raw(edid));
}

if (dcp->nr_modes && apple_connector->drm_edid)
drm_edid_connector_update(connector, apple_connector->drm_edid);

Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/apple/iomfb_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ void dcp_ack(struct apple_dcp *dcp, enum dcp_context_id context);
*/
struct dcp_rect drm_to_dcp_rect(struct drm_rect *rect);

u32 drm_format_to_dcp(u32 drm);
u32 drm_format_to_dcp_sdr(u32 drm);
u32 drm_format_to_dcp_hdr(u32 drm);

/* The user may own drm_display_mode, so we need to search for our copy */
struct dcp_display_mode *lookup_mode(struct apple_dcp *dcp,
Expand Down
60 changes: 57 additions & 3 deletions drivers/gpu/drm/apple/iomfb_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,24 @@ int DCP_FW_NAME(iomfb_modeset)(struct apple_dcp *dcp,
return 0;
}

extern u32 swap_hdr_colorspace;
extern u32 swap_hdr_transferfunc;
extern u32 swap_hdr_brightness;

static bool drm_format_maybe_hdr(u32 format)
{
switch (format) {
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
return false;

default:
return true;
}
}

void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, struct drm_atomic_state *state)
{
struct drm_plane *plane;
Expand Down Expand Up @@ -1374,11 +1392,47 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru
if (obj)
req->surf_iova[l] = obj->dma_addr + fb->offsets[0];

u32 format = drm_format_to_dcp_sdr(fb->format->format);
u32 colorspace = DCP_COLORSPACE_NATIVE;
u32 transferfunc = DCP_XFER_FUNC_SDR;

if (plane->type == DRM_PLANE_TYPE_PRIMARY && drm_format_maybe_hdr(fb->format->format)) {
if (dcp->connector->base.state->hdr_output_metadata) {
// HACK: hard code the values kwin & mutter use:
// DCP_COLORSPACE_BT2020
// DCP_XFER_FUNC_HDR # looks like PQ
//
// TODO need to pick the current colorspace and
// the transfer function from the drm properties
// (colorspace + HDR_OUTPUT_METADATA).
//
// For testing: You can set swap_hdr_colorspace
// and swap_hdr_transferfunc as parameters from
// userspace to try out different values.
//
colorspace = swap_hdr_colorspace;
transferfunc = swap_hdr_transferfunc;
format = drm_format_to_dcp_hdr(fb->format->format);

// force brightness to full for now.
if (!dcp->brightness.dac_hdr_restore && swap_hdr_brightness) {
dcp->brightness.dac_hdr_restore = dcp->brightness.dac;
dcp->brightness.dac = swap_hdr_brightness;
dcp->brightness.update = true;
}
} else if (dcp->brightness.dac_hdr_restore) {
// restore pre hdr brightness
dcp->brightness.dac = dcp->brightness.dac_hdr_restore;
dcp->brightness.dac_hdr_restore = 0;
dcp->brightness.update = true;
}
}

req->surf[l] = (struct DCP_FW_NAME(dcp_surface)){
.is_premultiplied = is_premultiplied,
.format = drm_format_to_dcp(fb->format->format),
.xfer_func = DCP_XFER_FUNC_SDR,
.colorspace = DCP_COLORSPACE_NATIVE,
.format = format,
.xfer_func = transferfunc,
.colorspace = colorspace,
.stride = fb->pitches[0],
.width = fb->width,
.height = fb->height,
Expand Down