Re: [RFC] drm/i915: Render decompression support for Gen9 and above

Daniel Vetter
2015-09-07T16:33:12Z

On Sat, Sep 05, 2015 at 01:12:50AM +0530, Vandana Kannan wrote:
> This patch includes enabling render decompression after checking all the
> requirements (format, tiling, rotation etc.). Along with this, the WAs
> mentioned in BSpec Workaround page have been implemented.
>
> This patch has been implemented on top of Nabendu/Chandra's NV12 patches.
>
> TODO:
> 1. Disable stereo 3D when render decomp is enabled (bit 7:6)
> 2. Render decompression must not be used in VTd pass-through mode
> 3. Program hashing select CHICKEN_MISC1 bit 15
> 4. For Gen10, add support for RGB 1010102
>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> ---
> drivers/gpu/drm/drm_atomic.c | 4 +
> drivers/gpu/drm/drm_crtc.c | 16 ++++
> drivers/gpu/drm/i915/intel_display.c | 174 +++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_drv.h | 7 ++
> drivers/gpu/drm/i915/intel_sprite.c | 35 +++++++
> include/drm/drm_crtc.h | 11 +++
> 6 files changed, 247 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 940f80b..d9004e8 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -607,6 +607,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
> state->src_h = val;
> } else if (property == config->rotation_property) {
> state->rotation = val;
> + } else if (property == config->compression_property) {
> + state->compression = val;

Please use a framebuffer modifier instead. Also this needs userspace.
-Daniel

> } else if (plane->funcs->atomic_set_property) {
> return plane->funcs->atomic_set_property(plane, state,
> property, val);
> @@ -654,6 +656,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
> *val = state->src_h;
> } else if (property == config->rotation_property) {
> *val = state->rotation;
> + } else if (property == config->compression_property) {
> + *val = state->compression;
> } else if (plane->funcs->atomic_get_property) {
> return plane->funcs->atomic_get_property(plane, state, property, val);
> } else {
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 474f328..66f817b 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -5778,6 +5778,22 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
> }
> EXPORT_SYMBOL(drm_mode_create_rotation_property);
>
> +struct drm_property *drm_mode_create_compression_property(
> + struct drm_device *dev,
> + unsigned int comp_caps)
> +{
> + static const struct drm_prop_enum_list props[] = {
> + { DRM_COMP_NONE, "Not compression capable" },
> + { DRM_COMP_RENDER, "Only render decompression" },
> + };
> +
> + return drm_property_create_bitmask(dev, 0, "render compression",
> + props, ARRAY_SIZE(props),
> + comp_caps);
> +}
> +EXPORT_SYMBOL(drm_mode_create_compression_property);
> +
> +
> /**
> * DOC: Tile group
> *
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 59d6736..115736f 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3120,8 +3120,47 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>
> hphase = 0x00010001; /* use trip for both Y and UV */
> vphase = 0x00012000; /* use trip for Y and phase 0.5 for UV */
> +
> + /*
> + * On SKL-C and BXT-A,
> + * when the plane source pixel format is NV12,
> + * the CHICKEN_PIPESL_* register bit 22 must be
> + * set to 1
> + */
> + if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
> + INTEL_REVID(dev) == SKL_REVID_C0))
> + I915_WRITE(CHICKEN_PIPESL_1(pipe),
> + I915_READ(CHICKEN_PIPESL_1(pipe)) |
> + HSW_FBCQ_DIS);
> }
> }
> +
> + if (plane->state->compression) {
> + /*
> + * FIXME: Check if aux_dist ad aux_stride can be taken as it
> + * is from userspace.
> + */
> + aux_dist = fb->offsets[1];
> + aux_stride = fb->pitches[1];
> + /*
> + * For SKL and BXT,
> + * When the render compression is enabled with plane
> + * width greater than 3840 and horizontal panning,
> + * the stride programmed in the PLANE_STRIDE register
> + * must be multiple of 4.
> + */
> + if (x > 3840 && x_offset != 0)
> + stride = stride - (stride % 4);
> + if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
> + INTEL_REVID(dev) == SKL_REVID_C0))
> + I915_WRITE(CHICKEN_PIPESL_1(pipe),
> + I915_READ(CHICKEN_PIPESL_1(pipe)) &
> + ~HSW_FBCQ_DIS);
> + plane_ctl |= PLANE_CTL_DECOMPRESSION_ENABLE;
> + } else {
> + plane_ctl &= ~PLANE_CTL_DECOMPRESSION_ENABLE;
> + }
> +
> plane_offset = y_offset << 16 | x_offset;
>
> I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
> @@ -11760,6 +11799,29 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> plane_state->rotation != BIT(DRM_ROTATE_0))
> intel_crtc->atomic.disable_fbc = true;
>
> + if (INTEL_INFO(dev)->gen >= 9) {
> + if (plane_state->compression) {
> + ret = skl_check_compression(dev,
> + to_intel_plane(plane),
> + to_intel_plane_state(plane_state),
> + intel_crtc->pipe);
> + if (ret)
> + return ret;
> + }
> + }
> +
> + /*
> + * Disable FBC if render decompression has to be enabled.
> + * FIXME: If FBC is disabled here because render decomp
> + * has to be enabled, then in update_primary_plane(), if
> + * render decomp is disabled for some reason, we need to
> + * enable FBC ?
> + */
> + if (IS_SKYLAKE(dev) && dev_priv->fbc.crtc == intel_crtc &&
> + plane_state->compression) {
> + intel_crtc->atomic.disable_fbc = true;
> + }
> +
> /*
> * BDW signals flip done immediately if the plane
> * is disabled, even if the plane enable is already
> @@ -11778,6 +11840,16 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> intel_crtc->atomic.update_sprite_watermarks |=
> 1 << i;
> }
> + if (INTEL_INFO(dev)->gen >= 9) {
> + if (plane_state->compression) {
> + ret = skl_check_compression(dev,
> + to_intel_plane(plane),
> + to_intel_plane_state(plane_state),
> + intel_crtc->pipe);
> + if (ret)
> + return ret;
> + }
> + }
> }
> return 0;
> }
> @@ -13495,6 +13567,88 @@ skl_max_scale(struct intel_crtc *intel_crtc,
> return max_scale;
> }
>
> +int skl_check_compression(struct drm_device *dev,
> + struct intel_plane *intel_plane,
> + struct intel_plane_state *plane_state,
> + enum pipe pipe)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct drm_rect *src = &plane_state->src;
> + struct drm_framebuffer *fb;
> + int i;
> +
> + fb = intel_plane ? plane_state->base.fb : NULL;
> +
> + /*
> + * TODO:
> + * 1. Disable stereo 3D when render decomp is enabled (bit 7:6)
> + * 2. Render decompression must not be used in VTd pass-through mode
> + * 3. Program hashing select CHICKEN_MISC1 bit 15
> + */
> +
> + /*
> + * On SKL A and SKL B,
> + * Do not enable render decompression when the plane
> + * width is smaller than 32 pixels or greater than
> + * 2048 pixels
> + */
> + if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) < SKL_REVID_C0)
> + && ((src->x1 >> 16) > 2048))
> + plane_state->base.compression = DRM_COMP_NONE;
> +
> + if (!plane_state->base.compression)
> + return -EINVAL;
> +
> + /*
> + * On SKL:*:C and BXT:*:A, there is a possible hang with NV12 format.
> + * WA: When the plane source pixel format is NV12,
> + * the CHICKEN_PIPESL_* register bit 22 must be set to 1 and the
> + * render decompression must not be enabled on any of the planes in
> + * that pipe.
> + */
> + if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
> + INTEL_REVID(dev) == SKL_REVID_C0)) {
> + struct drm_plane *drm_plane;
> + struct drm_plane_state *state;
> +
> + for_each_plane(dev_priv, pipe, i) {
> + drm_plane = drm_plane_from_index(dev, i);
> + if (drm_plane) {
> + state = drm_plane->state;
> + if (state) {
> + if (state->fb &&
> + state->fb->pixel_format
> + == DRM_FORMAT_NV12) {
> + plane_state->base.compression =
> + DRM_COMP_NONE;
> + }
> + }
> + }
> + }
> + }
> +
> + if (!plane_state->base.compression)
> + return -EINVAL;
> +
> + /*
> + * Conditions to satisfy before enabling render decomp.
> + * SKL+
> + * Pipe A & B, Planes 1 & 2
> + * RGB8888 Tile-Y format
> + * 0/180 rotation
> + */
> + if ((pipe == PIPE_C) ||
> + ((fb->pixel_format != DRM_FORMAT_XRGB8888) &&
> + (fb->pixel_format != DRM_FORMAT_ARGB8888)) ||
> + intel_rotation_90_or_270(plane_state->base.rotation) ||
> + ((fb->modifier[0] == DRM_FORMAT_MOD_NONE) ||
> + (fb->modifier[0] == I915_FORMAT_MOD_X_TILED))) {
> + plane_state->base.compression = DRM_COMP_NONE;
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> static int
> intel_check_primary_plane(struct drm_plane *plane,
> struct intel_crtc_state *crtc_state,
> @@ -13670,11 +13824,31 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
> if (INTEL_INFO(dev)->gen >= 4)
> intel_create_rotation_property(dev, primary);
>
> + intel_create_compression_property(dev, primary);
> +
> drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
>
> return &primary->base;
> }
>
> +void intel_create_compression_property(struct drm_device *dev,
> + struct intel_plane *plane)
> +{
> + /* Render compression is applicable only for plane 1 & 2 */
> + if (INTEL_INFO(dev)->gen >= 9 && (plane->plane <= 1)) {
> + if (!dev->mode_config.compression_property)
> + dev->mode_config.compression_property =
> + drm_mode_create_compression_property(dev,
> + BIT(DRM_COMP_NONE) |
> + BIT(DRM_COMP_RENDER));
> +
> + if (dev->mode_config.compression_property)
> + drm_object_attach_property(&plane->base.base,
> + dev->mode_config.compression_property,
> + plane->base.state->compression);
> + }
> +}
> +
> void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane)
> {
> if (!dev->mode_config.rotation_property) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 6cd6cb0..bae22eb 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1090,6 +1090,13 @@ intel_rotation_90_or_270(unsigned int rotation)
> void intel_create_rotation_property(struct drm_device *dev,
> struct intel_plane *plane);
>
> +void intel_create_compression_property(struct drm_device *dev,
> + struct intel_plane *plane);
> +int skl_check_compression(struct drm_device *dev,
> + struct intel_plane *intel_plane,
> + struct intel_plane_state *plane_state,
> + enum pipe pipe);
> +
> /* shared dpll functions */
> struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
> void assert_shared_dpll(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 2f9f856..c6cf4ad 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -275,8 +275,41 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>
> hphase = 0x00010001; /* use trip for both Y and UV */
> vphase = 0x00012000; /* use trip for Y and phase 0.5 for UV */
> +
> + if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
> + INTEL_REVID(dev) == SKL_REVID_C0))
> + I915_WRITE(CHICKEN_PIPESL_1(pipe),
> + I915_READ(CHICKEN_PIPESL_1(pipe)) |
> + HSW_FBCQ_DIS);
> }
> }
> +
> + if (drm_plane->state->compression) {
> + /*
> + * FIXME: Check if aux_dist ad aux_stride can be taken as it
> + * is from userspace.
> + */
> + aux_dist = fb->offsets[1];
> + aux_stride = fb->pitches[1];
> + /*
> + * For SKL and BXT,
> + * When the render compression is enabled with plane
> + * width greater than 3840 and horizontal panning,
> + * the stride programmed in the PLANE_STRIDE register
> + * must be multiple of 4.
> + */
> + if (x > 3840 && x_offset != 0)
> + stride = stride - (stride % 4);
> + if (IS_BROXTON(dev) || (IS_SKYLAKE(dev) &&
> + INTEL_REVID(dev) == SKL_REVID_C0))
> + I915_WRITE(CHICKEN_PIPESL_1(pipe),
> + I915_READ(CHICKEN_PIPESL_1(pipe)) &
> + ~HSW_FBCQ_DIS);
> + plane_ctl |= PLANE_CTL_DECOMPRESSION_ENABLE;
> + } else {
> + plane_ctl &= ~PLANE_CTL_DECOMPRESSION_ENABLE;
> + }
> +
> plane_offset = y_offset << 16 | x_offset;
>
> I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
> @@ -1217,6 +1250,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
>
> intel_create_rotation_property(dev, intel_plane);
>
> + intel_create_compression_property(dev, intel_plane);
> +
> drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
>
> out:
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 75f49c1..02a9aaa 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -93,6 +93,10 @@ static inline uint64_t I642U64(int64_t val)
> #define DRM_REFLECT_X 4
> #define DRM_REFLECT_Y 5
>
> +/* render compression property bits */
> +#define DRM_COMP_NONE 0
> +#define DRM_COMP_RENDER 1
> +
> enum drm_connector_force {
> DRM_FORCE_UNSPECIFIED,
> DRM_FORCE_OFF,
> @@ -783,6 +787,9 @@ struct drm_plane_state {
> /* Plane rotation */
> unsigned int rotation;
>
> + /* Render compression */
> + unsigned int compression;
> +
> struct drm_atomic_state *state;
> };
>
> @@ -1114,6 +1121,7 @@ struct drm_mode_config {
> struct drm_property *tile_property;
> struct drm_property *plane_type_property;
> struct drm_property *rotation_property;
> + struct drm_property *compression_property;
> struct drm_property *prop_src_x;
> struct drm_property *prop_src_y;
> struct drm_property *prop_src_w;
> @@ -1507,6 +1515,9 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);
> extern const char *drm_get_format_name(uint32_t format);
> extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
> unsigned int supported_rotations);
> +extern struct drm_property *drm_mode_create_compression_property(
> + struct drm_device *dev,
> + unsigned int comp_caps);
> extern unsigned int drm_rotation_simplify(unsigned int rotation,
> unsigned int supported_rotations);
>
> --
> 1.9.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

--
Daniel Vetter
Software Engineer, Intel Corporation