[PATCH v3 1/3] drm/connector: Add generic underscan properties
Brian Starkey
Brian.Starkey at arm.com
Thu Nov 22 17:36:58 UTC 2018
Hi Boris,
Just because I happened to read the docs in here, one typo below:
On Thu, Nov 22, 2018 at 12:23:29PM +0100, Boris Brezillon wrote:
>We have 3 drivers defining the "underscan", "underscan hborder" and
>"underscan vborder" properties (radeon, amd and nouveau) and we are
>about to add the same kind of thing in VC4.
>
>Define generic underscan props and add new fields to the drm_connector
>state so that the property parsing logic can be shared by all DRM
>drivers.
>
>A driver can now attach underscan properties to its connector through
>the drm_connector_attach_underscan_properties() helper, and can
>check/apply the underscan setup based on the
>drm_connector_state->underscan fields.
>
>Signed-off-by: Boris Brezillon <boris.brezillon at bootlin.com>
>---
>Changes in v3:
>- None
>
>Changes in v2:
>- Add a new section in the connector props doc to describe underscan
> props
>- Fix description of auto mode (auto means apply underscan for HDMI
> monitors only)
>- Fix description of vborder/hborder:
> right_border = left_border = hborder
> top_border = bottom_border = vborder
> not
> right_border = left_border = hborder / 2
> top_border = bottom_border = vborder / 2
>- Rename drm_underscan into drm_underscan_state
>---
> drivers/gpu/drm/drm_atomic_uapi.c | 12 +++
> drivers/gpu/drm/drm_connector.c | 127 ++++++++++++++++++++++++++++++
> include/drm/drm_connector.h | 80 +++++++++++++++++++
> 3 files changed, 219 insertions(+)
>
>diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
>index d5b7f315098c..39db6e31c565 100644
>--- a/drivers/gpu/drm/drm_atomic_uapi.c
>+++ b/drivers/gpu/drm/drm_atomic_uapi.c
>@@ -740,6 +740,12 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
>
> return set_out_fence_for_connector(state->state, connector,
> fence_ptr);
>+ } else if (property == connector->underscan_mode_property) {
>+ state->underscan.mode = val;
>+ } else if (property == connector->underscan_hborder_property) {
>+ state->underscan.hborder = val;
>+ } else if (property == connector->underscan_vborder_property) {
>+ state->underscan.vborder = val;
> } else if (connector->funcs->atomic_set_property) {
> return connector->funcs->atomic_set_property(connector,
> state, property, val);
>@@ -799,6 +805,12 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
> *val = state->scaling_mode;
> } else if (property == connector->content_protection_property) {
> *val = state->content_protection;
>+ } else if (property == connector->underscan_mode_property) {
>+ *val = state->underscan.mode;
>+ } else if (property == connector->underscan_hborder_property) {
>+ *val = state->underscan.hborder;
>+ } else if (property == connector->underscan_vborder_property) {
>+ *val = state->underscan.vborder;
> } else if (property == config->writeback_fb_id_property) {
> /* Writeback framebuffer is one-shot, write and forget */
> *val = 0;
>diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
>index c555e17ab8d7..170317248da6 100644
>--- a/drivers/gpu/drm/drm_connector.c
>+++ b/drivers/gpu/drm/drm_connector.c
>@@ -971,6 +971,38 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
> * can also expose this property to external outputs, in which case they
> * must support "None", which should be the default (since external screens
> * have a built-in scaler).
>+ *
>+ * Connectors for non-analog outputs may also have standardized underscan
>+ * properties (drivers can set this up by calling
>+ * drm_connector_attach_content_protection_property() on initialization):
Should be drm_connector_attach_underscan_properties()
Cheers,
-Brian
>+ *
>+ * underscan:
>+ * This properties defines whether underscan is activated or not, and when
>+ * it is activated, how the horizontal and vertical borders are calculated:
>+ *
>+ * off:
>+ * Underscan is disabled. The output image shouldn't be scaled to
>+ * take screen borders into account.
>+ * on:
>+ * Underscan is activated and horizontal and vertical borders are
>+ * specified through the "underscan hborder" and
>+ * "underscan vborder" properties.
>+ * auto:
>+ * Underscan is activated only for HDMI monitors.
>+ *
>+ * underscan hborder:
>+ * Horizontal border expressed in pixels. The border is symmetric, which
>+ * means you'll have a border of 'hborder' pixels on the left and on the
>+ * same border on the right.
>+ * When this value is 0 and underscan is "on" or "auto", the driver will
>+ * pick a default value (the default value is driver dependent).
>+ *
>+ * underscan vborder:
>+ * Vertical border expressed in pixels. The border is symmetric, which
>+ * means you'll have a border of 'vborder' pixels on the top and the same
>+ * border on the bottom.
>+ * When this value is 0 and underscan is "on" or "auto", the driver will
>+ * pick a default value (the default value is driver dependent).
> */
>
> int drm_connector_create_standard_properties(struct drm_device *dev)
>@@ -1241,6 +1273,101 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
> }
> EXPORT_SYMBOL(drm_mode_create_tv_properties);
>
>+static const struct drm_prop_enum_list drm_underscan_mode_enum_list[] = {
>+ { DRM_UNDERSCAN_OFF, "off" },
>+ { DRM_UNDERSCAN_ON, "on" },
>+ { DRM_UNDERSCAN_AUTO, "auto" },
>+};
>+
>+/**
>+ * drm_connector_attach_underscan_properties - attach atomic underscan
>+ * properties
>+ * @connector: connector to attach underscan mode properties on.
>+ * @mode_mask: bitmask of %DRM_UNDERSCAN_XX modes encoding the supported
>+ * underscan modes.
>+ * @max_hborder: maximum size of the horizontal border expressed in pixels.
>+ * Should be > 0.
>+ * @max_vborder: maximum size of the vertical border expressed in pixels.
>+ * Should be > 0.
>+ *
>+ * This is used to add support for underscan to atomic drivers.
>+ * The underscan config will be set to &drm_connector_state.underscan
>+ * and can be used from &drm_connector_helper_funcs->atomic_check for
>+ * validation.
>+ *
>+ * Returns:
>+ * Zero on success, negative errno on failure.
>+ */
>+int drm_connector_attach_underscan_properties(struct drm_connector *connector,
>+ u32 mode_mask, u64 max_hborder,
>+ u64 max_vborder)
>+{
>+ unsigned int i, nmodes = ARRAY_SIZE(drm_underscan_mode_enum_list);
>+ struct drm_device *dev = connector->dev;
>+ struct drm_property *prop;
>+
>+ if (!max_hborder || !max_vborder)
>+ return -EINVAL;
>+
>+ if (!hweight32(mode_mask) || (mode_mask & ~GENMASK(nmodes - 1, 0)))
>+ return -EINVAL;
>+
>+ prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, "underscan",
>+ hweight32(mode_mask));
>+ if (!prop)
>+ return -ENOMEM;
>+
>+ for (i = 0; i < ARRAY_SIZE(drm_underscan_mode_enum_list); i++) {
>+ const struct drm_prop_enum_list *entry;
>+ int ret;
>+
>+ if (!(BIT(i) & mode_mask))
>+ continue;
>+
>+ entry = &drm_underscan_mode_enum_list[i];
>+ ret = drm_property_add_enum(prop, entry->type, entry->name);
>+ if (ret)
>+ goto err_free_mode_prop;
>+ }
>+
>+ connector->underscan_mode_property = prop;
>+
>+ prop = drm_property_create_range(dev, 0, "underscan hborder", 0,
>+ max_hborder);
>+ if (!prop)
>+ goto err_free_mode_prop;
>+
>+ connector->underscan_hborder_property = prop;
>+
>+ prop = drm_property_create_range(dev, 0, "underscan vborder", 0,
>+ max_vborder);
>+ if (!prop)
>+ goto err_free_hborder_prop;
>+
>+ connector->underscan_vborder_property = prop;
>+
>+ drm_object_attach_property(&connector->base,
>+ connector->underscan_mode_property,
>+ DRM_UNDERSCAN_OFF);
>+ drm_object_attach_property(&connector->base,
>+ connector->underscan_hborder_property, 0);
>+ drm_object_attach_property(&connector->base,
>+ connector->underscan_vborder_property, 0);
>+
>+ return 0;
>+
>+err_free_hborder_prop:
>+ drm_property_destroy(dev, connector->underscan_hborder_property);
>+ connector->underscan_hborder_property = NULL;
>+
>+err_free_mode_prop:
>+ drm_property_destroy(dev, connector->underscan_mode_property);
>+ connector->underscan_mode_property = NULL;
>+
>+ return -ENOMEM;
>+}
>+EXPORT_SYMBOL(drm_connector_attach_underscan_properties);
>+
> /**
> * drm_mode_create_scaling_mode_property - create scaling mode property
> * @dev: DRM device
>diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>index 5b3cf909fd5e..14d423dc7a14 100644
>--- a/include/drm/drm_connector.h
>+++ b/include/drm/drm_connector.h
>@@ -377,6 +377,53 @@ struct drm_tv_connector_state {
> unsigned int hue;
> };
>
>+/**
>+ * enum drm_underscan_mode - Underscan mode
>+ *
>+ * This enum is used to track the underscan mode.
>+ *
>+ * @DRM_UNDERSCAN_OFF: No underscan applied, the output image will be unchanged
>+ * @DRM_UNDERSCAN_ON: Underscan is enabled, and horizontal/vertical border size
>+ * are specified through the &struct_drm_underscan->hborder
>+ * and &struct_drm_underscan->vborder fields.
>+ * @DRM_UNDERSCAN_AUTO: Underscan is enabled and &struct_drm_underscan->hborder
>+ * and &struct_drm_underscan->vborder are guessed by the
>+ * driver.
>+ */
>+enum drm_underscan_mode {
>+ DRM_UNDERSCAN_OFF,
>+ DRM_UNDERSCAN_ON,
>+ DRM_UNDERSCAN_AUTO,
>+};
>+
>+/**
>+ * struct drm_underscan_state - Underscan properties attached to a connector
>+ * state
>+ *
>+ * This can be used to tell the CRTC how the image should be scaled/placed in
>+ * order to cover fit in the display connected through this connector. Most of
>+ * the time used to address situations where the display borders are hidden.
>+ * Can also be used to compensate overscan done on the display side.
>+ */
>+struct drm_underscan_state {
>+ /**
>+ * @mode: Underscan mode.
>+ */
>+ enum drm_underscan_mode mode;
>+
>+ /**
>+ * @hborder: Horizontal border. This values encodes both the left and
>+ * right borders: left_border = right_border = hborder / 2.
>+ */
>+ unsigned int hborder;
>+
>+ /**
>+ * @vborder: Vertical border. This values encodes both the top and
>+ * bottom borders: top_border = bottom_border = vborder / 2.
>+ */
>+ unsigned int vborder;
>+};
>+
> /**
> * struct drm_connector_state - mutable connector state
> */
>@@ -461,6 +508,13 @@ struct drm_connector_state {
> * drm_writeback_signal_completion()
> */
> struct drm_writeback_job *writeback_job;
>+
>+ /**
>+ * @underscan: Underscan information. Most commonly used to adjust
>+ * image when the display has borders covering part of the image of
>+ * when it's doing overscan on its own.
>+ */
>+ struct drm_underscan_state underscan;
> };
>
> /**
>@@ -924,6 +978,29 @@ struct drm_connector {
> */
> struct drm_property_blob *path_blob_ptr;
>
>+ /**
>+ * @underscan_mode_property: Optional connector underscan mode. Used by
>+ * the driver to scale the output image and compensate an overscan done
>+ * on the display side.
>+ */
>+ struct drm_property *underscan_mode_property;
>+
>+ /**
>+ * @underscan_hborder_property: Optional connector underscan horizontal
>+ * border (expressed in pixels). Used by the driver to adjust the
>+ * output image position and compensate an overscan done on the display
>+ * side.
>+ */
>+ struct drm_property *underscan_hborder_property;
>+
>+ /**
>+ * @underscan_hborder_property: Optional connector underscan vertical
>+ * border (expressed in pixels). Used by the driver to adjust the
>+ * output image position and compensate an overscan done on the display
>+ * side.
>+ */
>+ struct drm_property *underscan_vborder_property;
>+
> #define DRM_CONNECTOR_POLL_HPD (1 << 0)
> #define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
> #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
>@@ -1180,6 +1257,9 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev);
> int drm_mode_create_tv_properties(struct drm_device *dev,
> unsigned int num_modes,
> const char * const modes[]);
>+int drm_connector_attach_underscan_properties(struct drm_connector *connector,
>+ u32 mode_mask, u64 max_hborder,
>+ u64 max_vborder);
> int drm_mode_create_scaling_mode_property(struct drm_device *dev);
> int drm_connector_attach_content_type_property(struct drm_connector *dev);
> int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
>--
>2.17.1
>
>_______________________________________________
>dri-devel mailing list
>dri-devel at lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/dri-devel
More information about the dri-devel
mailing list