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@xxxxxxxxxxx> >--- >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@xxxxxxxxxxxxxxxxxxxxx >https://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel