Skip to content

BCM2711 KMS YUV output #4201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
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
4 changes: 4 additions & 0 deletions drivers/gpu/drm/drm_atomic_uapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
state->content_protection = val;
} else if (property == config->hdcp_content_type_property) {
state->hdcp_content_type = val;
} else if (property == connector->color_format_property) {
state->color_format = val;
} else if (property == connector->colorspace_property) {
state->colorspace = val;
} else if (property == config->writeback_fb_id_property) {
Expand Down Expand Up @@ -828,6 +830,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
*val = state->picture_aspect_ratio;
} else if (property == config->content_type_property) {
*val = state->content_type;
} else if (property == connector->color_format_property) {
*val = state->color_format;
} else if (property == connector->colorspace_property) {
*val = state->colorspace;
} else if (property == connector->scaling_mode_property) {
Expand Down
86 changes: 86 additions & 0 deletions drivers/gpu/drm/drm_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,26 @@ int drm_connector_update_edid_property(struct drm_connector *connector,
}
}

if (connector->supported_color_formats_property) {
u32 fmts = DRM_COLOR_FORMAT_RGB444;

if ((connector->supported_output_formats & DRM_COLOR_FORMAT_YCRCB444) &&
(connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444))
fmts |= DRM_COLOR_FORMAT_YCRCB444;

if ((connector->supported_output_formats & DRM_COLOR_FORMAT_YCRCB422) &&
(connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB422))
fmts |= DRM_COLOR_FORMAT_YCRCB422;

if ((connector->supported_output_formats & DRM_COLOR_FORMAT_YCRCB420) &&
(connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420))
fmts |= DRM_COLOR_FORMAT_YCRCB420;

drm_object_property_set_value(&connector->base,
connector->supported_color_formats_property,
fmts);
}

drm_object_property_set_value(&connector->base,
dev->mode_config.non_desktop_property,
connector->display_info.non_desktop);
Expand Down Expand Up @@ -2143,6 +2163,72 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_connector_attach_max_bpc_property);

static const struct drm_prop_enum_list hdmi_output_fmts[] = {
{ __builtin_ffs(DRM_COLOR_FORMAT_RGB444) - 1, "RGB444" },
{ __builtin_ffs(DRM_COLOR_FORMAT_YCRCB444) - 1, "YCrCb444" },
{ __builtin_ffs(DRM_COLOR_FORMAT_YCRCB422) - 1, "YCrCb422" },
{ __builtin_ffs(DRM_COLOR_FORMAT_YCRCB420) - 1, "YCrCb420" },
};

/**
* drm_connector_create_hdmi_color_formats_properties - create hdmi color formats properties
* @connector: connector to create the output property on.
* @supported_fmts: bitmask of supported DRM_COLOR_FORMAT_*
*
* Called by a driver the first time it's needed, must be attached to
* desired HDMI connectors.
*
* Returns:
* Zero on success, negative errno on failure.
*/
int drm_connector_create_hdmi_color_formats_properties(struct drm_connector *connector,
u32 supported_fmts)
{
struct drm_device *dev = connector->dev;
struct drm_property *prop;

connector->supported_output_formats = supported_fmts;
prop = connector->supported_color_formats_property;
if (!prop) {
prop = drm_property_create_bitmask(dev, DRM_MODE_PROP_IMMUTABLE,
"available output formats",
hdmi_output_fmts,
ARRAY_SIZE(hdmi_output_fmts),
DRM_COLOR_FORMAT_RGB444 |
DRM_COLOR_FORMAT_YCRCB444 |
DRM_COLOR_FORMAT_YCRCB422 |
DRM_COLOR_FORMAT_YCRCB420);
if (!prop)
return -ENOMEM;

connector->supported_color_formats_property = prop;
}

/*
* Report only RGB444 for now, this will be updated using the
* EDID later on depending on the display capabilities.
*/
drm_object_attach_property(&connector->base, prop, DRM_COLOR_FORMAT_RGB444);

prop = connector->color_format_property;
if (!prop) {
prop = drm_property_create_enum(dev, 0,
"output format",
hdmi_output_fmts,
ARRAY_SIZE(hdmi_output_fmts));
if (!prop)
return -ENOMEM;

connector->color_format_property = prop;
}

drm_object_attach_property(&connector->base, prop, DRM_COLOR_FORMAT_RGB444);
connector->state->color_format = DRM_COLOR_FORMAT_RGB444;

return 0;
}
EXPORT_SYMBOL(drm_connector_create_hdmi_color_formats_properties);

/**
* drm_connector_attach_hdr_output_metadata_property - attach "HDR_OUTPUT_METADA" property
* @connector: connector to attach the property on.
Expand Down
41 changes: 37 additions & 4 deletions drivers/gpu/drm/drm_edid.c
Original file line number Diff line number Diff line change
Expand Up @@ -4955,7 +4955,7 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
* modes and forbids YCRCB422 support for all video modes per
* HDMI 1.3 spec.
*/
info->color_formats = DRM_COLOR_FORMAT_RGB444;
info->color_formats |= DRM_COLOR_FORMAT_RGB444;

/* YCRCB444 is optional according to spec. */
if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
Expand Down Expand Up @@ -5703,13 +5703,13 @@ static const u32 hdmi_colorimetry_val[] = {
#undef ACE

/**
* drm_hdmi_avi_infoframe_colorspace() - fill the HDMI AVI infoframe
* colorspace information
* drm_hdmi_avi_infoframe_colorimetry() - fill the HDMI AVI infoframe
* colorimetry information
* @frame: HDMI AVI infoframe
* @conn_state: connector state
*/
void
drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
drm_hdmi_avi_infoframe_colorimetry(struct hdmi_avi_infoframe *frame,
const struct drm_connector_state *conn_state)
{
u32 colorimetry_val;
Expand All @@ -5728,6 +5728,39 @@ drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
frame->extended_colorimetry = (colorimetry_val >> 2) &
EXTENDED_COLORIMETRY_MASK;
}
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorimetry);

/**
* drm_hdmi_avi_infoframe_colorspace() - fill the HDMI AVI infoframe
* colorspace information
* @frame: HDMI AVI infoframe
* @conn_state: connector state
*/
void
drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
const struct drm_connector_state *conn_state)
{
switch (BIT(conn_state->color_format)) {
case DRM_COLOR_FORMAT_YCRCB444:
frame->colorspace = HDMI_COLORSPACE_YUV444;
break;

case DRM_COLOR_FORMAT_YCRCB422:
frame->colorspace = HDMI_COLORSPACE_YUV422;
break;

case DRM_COLOR_FORMAT_YCRCB420:
frame->colorspace = HDMI_COLORSPACE_YUV420;
break;

case DRM_COLOR_FORMAT_RGB444:
frame->colorspace = HDMI_COLORSPACE_RGB;
break;

default:
break;
}
}
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorspace);

/**
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/display/intel_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder,
else
frame->colorspace = HDMI_COLORSPACE_RGB;

drm_hdmi_avi_infoframe_colorspace(frame, conn_state);
drm_hdmi_avi_infoframe_colorimetry(frame, conn_state);

/* nonsense combination */
drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&
Expand Down
Loading