[PATCH v5 09/17] drm: create hdmi output property
Daniel Vetter
daniel at ffwll.ch
Tue Jul 4 15:36:27 UTC 2017
On Tue, Jul 04, 2017 at 07:41:56PM +0530, Shashank Sharma wrote:
> HDMI displays can support various output types, based on
> the color space and subsampling type. The possible
> outputs from a HDMI 2.0 monitor could be:
> - RGB
> - YCBCR 444
> - YCBCR 422
> - YCBCR 420
>
> This patch adds a drm property "hdmi_output_format", using which,
> a user can specify its preference, for the HDMI output type. The
> output type enums are similar to the mentioned outputs above. To
> handle various subsampling of YCBCR output types, this property
> allows two special cases:
> - DRM_HDMI_OUTPUT_YCBCR_HQ
> This indicates preferred output should be YCBCR output, with highest
> subsampling rate by the source/sink, which can be typically:
> - ycbcr444
> - ycbcr422
> - ycbcr420
> - DRM_HDMI_OUTPUT_YCBCR_LQ
> This indicates preferred output should be YCBCR output, with lowest
> subsampling rate supported by source/sink, which can be:
> - ycbcr420
> - ycbcr422
> - ycbcr444
>
> Default value of the property is set to 0 = RGB, so no changes if you
> dont set the property.
>
> PS: While doing modeset for YCBCR 420 only modes, this property is
> ignored, as those timings can be supported only in YCBCR 420
> output mode.
>
> V2: Added description for the new variable to address build warning
> V3: Rebase
> V4: Rebase
> V5: Added get_property counterpart to fix IGT BAT failures (BAT/CI)
> Danvet:
> - Add documentation for the new property
> - Create a sub-section for HDMI properties, and add documentation for
> few more HDMI propeties. Added documentation for:
> - Broadcast RGB
> - aspect ratio
>
> Cc: Ville Syrjala <ville.syrjala at linux.intel.com>
> Cc: Jose Abreu <joabreu at synopsys.com>
> Cc: Daniel Vetter <daniel.vetter at intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma at intel.com>
Bunch more documentation nitpicks below. I'd personally also split up the
patch into documenting the existing props and adding the new format one.
Thanks, Daniel
> ---
> Documentation/gpu/drm-kms.rst | 12 +++++++
> drivers/gpu/drm/drm_atomic.c | 4 +++
> drivers/gpu/drm/drm_atomic_helper.c | 4 +++
> drivers/gpu/drm/drm_connector.c | 69 ++++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/drm_crtc_internal.h | 1 +
> drivers/gpu/drm/drm_mode_config.c | 4 +++
> drivers/gpu/drm/i915/intel_modes.c | 13 +++++++
> include/drm/drm_connector.h | 18 ++++++++++
> include/drm/drm_mode_config.h | 5 +++
> 9 files changed, 129 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index 3072841..dcdd6ff 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -508,6 +508,18 @@ Standard Connector Properties
> .. kernel-doc:: drivers/gpu/drm/drm_connector.c
> :doc: standard connector properties
>
> +Standard HDMI Properties
> +-----------------------------
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_connector.c
> + :doc: hdmi_output_format
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_connector.c
> + :doc: aspect ratio property
I'd have just created 1 DOC: section titled "standard HDMI properties" and
listed all of them in 1 comment block. People often forget to add the
include stanza in the .rst files, having bigger comments helps with that.
But feel free to go either way.
> +
> +.. kernel-doc:: drivers/gpu/drm/i915/intel_modes.c
> + :doc: Broadcast RGB property
Please no generic properties documented in driver code.
> +
> Plane Composition Properties
> ----------------------------
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 09ca662..adcb89d 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
> state->picture_aspect_ratio = val;
> } else if (property == connector->scaling_mode_property) {
> state->scaling_mode = val;
> + } else if (property == config->hdmi_output_property) {
> + state->hdmi_output = val;
> } else if (connector->funcs->atomic_set_property) {
> return connector->funcs->atomic_set_property(connector,
> state, property, val);
> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
> *val = state->picture_aspect_ratio;
> } else if (property == connector->scaling_mode_property) {
> *val = state->scaling_mode;
> + } else if (property == config->hdmi_output_property) {
> + *val = state->hdmi_output;
> } else if (connector->funcs->atomic_get_property) {
> return connector->funcs->atomic_get_property(connector,
> state, property, val);
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 23e4661..2e7459f 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
> if (old_connector_state->link_status !=
> new_connector_state->link_status)
> new_crtc_state->connectors_changed = true;
> +
> + if (old_connector_state->hdmi_output !=
> + new_connector_state->hdmi_output)
> + new_crtc_state->connectors_changed = true;
> }
>
> if (funcs->atomic_check)
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 8072e6e..8357918 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
> config->edid_property,
> 0);
>
> + if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
> + drm_object_attach_property(&connector->base,
> + config->hdmi_output_property,
> + 0);
> +
> drm_object_attach_property(&connector->base,
> config->dpms_property, 0);
>
> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
> };
> DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>
> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
> + { DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
> + { DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
> + { DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
> + { DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
> + { DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
> + { DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
> + { DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
> +};
> +
> +/**
> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
> + * @type: enum of output type
> + */
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
> +{
> + return drm_hdmi_output_enum_list[type].name;
> +}
> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
> +
> /**
> * drm_display_info_set_bus_formats - set the supported bus formats
> * @info: display info to store bus formats in
> @@ -697,7 +722,36 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
> { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
> };
> DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
> - drm_tv_subconnector_enum_list)
> + drm_tv_subconnector_enum_list);
> +
> +/**
> + * DOC: hdmi_output_format
> + *
> + * hdmi_output_format:
> + * Enum property which allows a userspace to provide its preference for a
> + * HDMI output format. Standard HDMI 1.4b outputs can support RGB/YCBCR444
> + * YCBCR422 output formats, whereas HDMI 2.0 outputs can additionally
> + * support YCBCR420 output. Default value of the property is HDMI output
> + * RGB.
> + *
> + * A driver can attach to this property, and then handle the HDMI output
> + * based on its capabilities and sink support. There are few helper
> + * functions available in drm_modes.c which can help in finding the best
> + * suitable output considering a sink/source/mode combination. Refer to
> + * drm_modes.c:drm_display_info_hdmi_output_type()
> + */
> +int drm_connector_create_hdmi_properties(struct drm_device *dev)
> +{
> + struct drm_property *prop;
> +
> + prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
> + drm_hdmi_output_enum_list,
> + ARRAY_SIZE(drm_hdmi_output_enum_list));
> + if (!prop)
> + return -ENOMEM;
> + dev->mode_config.hdmi_output_property = prop;
> + return 0;
> +}
>
> /**
> * DOC: standard connector properties
> @@ -1024,6 +1078,19 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
> }
> EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property);
>
> +
> +/**
> + * DOC: aspect ratio property
> + *
> + * aspect ratio:
> + * Enum property to override the HDMI output's aspect ratio.
> + * When this property is set, the aspect ratio of the frame in
> + * AVI infoframes is set as per the property value. For example
> + * if userspace sets the property value to DRM_MODE_PICTURE_ASPECT_4_3
> + * the output aspect ratio is set to 4:3 (regardless of the PAR of mode)
Would be good to document all possible values. Same for the other
properties, plus insert a link to the function that creates the property
(where we have that).
> + *
> + */
> +
> /**
> * drm_mode_create_aspect_ratio_property - create aspect ratio property
> * @dev: DRM device
> diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
> index d077c54..e6c4adc 100644
> --- a/drivers/gpu/drm/drm_crtc_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_internal.h
> @@ -140,6 +140,7 @@ int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
> struct drm_property *property,
> uint64_t value);
> int drm_connector_create_standard_properties(struct drm_device *dev);
> +int drm_connector_create_hdmi_properties(struct drm_device *dev);
> const char *drm_get_connector_force_name(enum drm_connector_force force);
>
> /* IOCTL */
> diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
> index d986225..3ba9262 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -210,6 +210,10 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
> if (ret)
> return ret;
>
> + ret = drm_connector_create_hdmi_properties(dev);
> + if (ret)
> + return ret;
We still create all the property values instead of just the ones that the
source hw supports. E.g. aspect ratio property is only created if needed,
not unconditionally on all connectors.
Note that users see properties through xrandr and the gui screen
configuration tools, adding properties that never do anything is
confusing, more for properties where you can select invalid values.
> +
> prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
> "type", drm_plane_type_enum_list,
> ARRAY_SIZE(drm_plane_type_enum_list));
> diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
> index 951e834..d07de45 100644
> --- a/drivers/gpu/drm/i915/intel_modes.c
> +++ b/drivers/gpu/drm/i915/intel_modes.c
> @@ -104,6 +104,19 @@ static const struct drm_prop_enum_list broadcast_rgb_names[] = {
> { INTEL_BROADCAST_RGB_LIMITED, "Limited 16:235" },
> };
>
> +/**
> + * DOC: Broadcast RGB property
> + *
> + * Broadcast RGB:
> + * Enum property to indicate RGB color range of a HDMI output.
> + * For limited range RGB outputs, a remapping of pixel values from 0-255
> + * should be remaped to a range of 16-235. When this property is set to
> + * Limited 16:235 and CTM is set, the hardware will be programmed with the
> + * result of the multiplication of CTM by the limited range matrix, to
> + * ensure the pixels normaly in the range 0..1.0 are remapped to the range
> + * 16/255..235/255.
> + *
> + */
> void
> intel_attach_broadcast_rgb_property(struct drm_connector *connector)
> {
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 4bc0882..3773600 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -319,6 +319,17 @@ struct drm_tv_connector_state {
> unsigned int hue;
> };
>
> +/* HDMI output pixel format */
> +enum drm_hdmi_output_type {
> + DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
> + DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
> + DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
> + DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
> + DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
> + DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
> + DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
> +};
> +
> /**
> * struct drm_connector_state - mutable connector state
> * @connector: backpointer to the connector
> @@ -363,6 +374,12 @@ struct drm_connector_state {
> * upscaling, mostly used for built-in panels.
> */
> unsigned int scaling_mode;
> +
> + /**
> + * @hdmi_output: Connector property to control the
> + * HDMI output mode (RGB/YCBCR444/422/420).
> + */
> + enum drm_hdmi_output_type hdmi_output;
> };
>
> /**
> @@ -991,6 +1008,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>
> const char *drm_get_connector_status_name(enum drm_connector_status status);
> const char *drm_get_subpixel_order_name(enum subpixel_order order);
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
> const char *drm_get_dpms_name(int val);
> const char *drm_get_dvi_i_subconnector_name(int val);
> const char *drm_get_dvi_i_select_name(int val);
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 4298171..1887261 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -740,6 +740,11 @@ struct drm_mode_config {
> * the position of the output on the host's screen.
> */
> struct drm_property *suggested_y_property;
> + /**
> + * @hdmi_output_property: output pixel format from HDMI display
> + * Default is set for RGB
> + */
> + struct drm_property *hdmi_output_property;
>
> /* dumb ioctl parameters */
> uint32_t preferred_depth, prefer_shadow;
> --
> 2.7.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list