This patch includes enabling render decompression (RC) after checking all the requirements (format, tiling, rotation etc.). Along with this, the WAs mentioned in BSpec Workaround page have been implemented. 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 5. RC-FBC workaround 6. RC watermark calculation The reason for using a plane property instead of fb modifier:- In Android, OGL passes a render compressed buffer to hardware composer (HWC), which would then request a flip on that buffer after checking if the target can support render compressed buffer. For example, only planes 1 and 2 on pipes 1 and 2 can support RC. In case the target cannot support it, HWC will revert back to OGL requesting for uncompressed buffer. Here, if plane property is used, OGL would send back the buffer (same ID) after decompression, marked uncompressed. If fb modifier was used, a different version of the buffer would have to be maintained for different combinations - in the simple case of render compressed vs uncompressed buffer, there would be 2 fbs with 2 IDs. So, in this case, OGL would give a reference to a fb with a different ID. To avoid the difficulty of keeping track of multiple fbs and the subsequent complexity in debug, the architecture forum decided to go ahead with a plane property for RC. [Mayuresh] Added the plane check in skl_check_compression() Signed-off-by: Vandana Kannan <vandana.kannan@xxxxxxxxx> Cc: Smith, Gary K <gary.k.smith@xxxxxxxxx> Cc: Daniel Stone <daniel@xxxxxxxxxxxxx> Cc: Daniel Vetter <daniel@xxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 22 ++++ drivers/gpu/drm/i915/intel_atomic_plane.c | 24 +++- drivers/gpu/drm/i915/intel_display.c | 206 +++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 24 +++- drivers/gpu/drm/i915/intel_sprite.c | 42 +++++- 6 files changed, 305 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f37ac12..bb47ee1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1929,6 +1929,7 @@ struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; + struct drm_property *render_comp_property; /* hda/i915 audio component */ struct i915_audio_component *audio_component; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7dfc400..773c37f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5756,6 +5756,28 @@ enum skl_disp_power_wells { _ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A), \ _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B)) +#define PLANE_AUX_DIST_1_A 0x701c0 +#define PLANE_AUX_DIST_2_A 0x702c0 +#define PLANE_AUX_DIST_1_B 0x711c0 +#define PLANE_AUX_DIST_2_B 0x712c0 +#define _PLANE_AUX_DIST_1(pipe) \ + _PIPE(pipe, PLANE_AUX_DIST_1_A, PLANE_AUX_DIST_1_B) +#define _PLANE_AUX_DIST_2(pipe) \ + _PIPE(pipe, PLANE_AUX_DIST_2_A, PLANE_AUX_DIST_2_B) +#define PLANE_AUX_DIST(pipe, plane) \ + _MMIO_PLANE(plane, _PLANE_AUX_DIST_1(pipe), _PLANE_AUX_DIST_2(pipe)) + +#define PLANE_AUX_OFFSET_1_A 0x701c4 +#define PLANE_AUX_OFFSET_2_A 0x702c4 +#define PLANE_AUX_OFFSET_1_B 0x711c4 +#define PLANE_AUX_OFFSET_2_B 0x712c4 +#define _PLANE_AUX_OFFSET_1(pipe) \ + _PIPE(pipe, PLANE_AUX_OFFSET_1_A, PLANE_AUX_OFFSET_1_B) +#define _PLANE_AUX_OFFSET_2(pipe) \ + _PIPE(pipe, PLANE_AUX_OFFSET_2_A, PLANE_AUX_OFFSET_2_B) +#define PLANE_AUX_OFFSET(pipe, plane) \ + _MMIO_PLANE(plane, _PLANE_AUX_OFFSET_1(pipe), _PLANE_AUX_OFFSET_2(pipe)) + /* legacy palette */ #define _LGC_PALETTE_A 0x4a000 #define _LGC_PALETTE_B 0x4a800 diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index e0b851a..c431333 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -230,8 +230,16 @@ intel_plane_atomic_get_property(struct drm_plane *plane, struct drm_property *property, uint64_t *val) { - DRM_DEBUG_KMS("Unknown plane property '%s'\n", property->name); - return -EINVAL; + struct drm_i915_private *dev_priv = state->plane->dev->dev_private; + struct intel_plane_state *intel_state = to_intel_plane_state(state); + + if (property == dev_priv->render_comp_property) { + *val = intel_state->render_comp_enable; + } else { + DRM_DEBUG_KMS("Unknown plane property '%s'\n", property->name); + return -EINVAL; + } + return 0; } /** @@ -252,6 +260,14 @@ intel_plane_atomic_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t val) { - DRM_DEBUG_KMS("Unknown plane property '%s'\n", property->name); - return -EINVAL; + struct drm_i915_private *dev_priv = state->plane->dev->dev_private; + struct intel_plane_state *intel_state = to_intel_plane_state(state); + + if (property == dev_priv->render_comp_property) { + intel_state->render_comp_enable = val; + } else { + DRM_DEBUG_KMS("Unknown plane property '%s'\n", property->name); + return -EINVAL; + } + return 0; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b2fcbe6..676507d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -117,6 +117,9 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); static void ironlake_pfit_enable(struct intel_crtc *crtc); static void intel_modeset_setup_hw_state(struct drm_device *dev); static void intel_pre_disable_primary(struct drm_crtc *crtc); +static int skl_check_compression(struct drm_device *dev, + struct intel_plane_state *plane_state, + enum pipe pipe, int x, int y); typedef struct { int min, max; @@ -3573,7 +3576,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, struct drm_framebuffer *fb = plane_state->base.fb; int pipe = intel_crtc->pipe; u32 plane_ctl; - unsigned int rotation = plane_state->base.rotation; + unsigned int rotation = plane_state->base.rotation, render_comp; u32 stride = skl_plane_stride(fb, 0, rotation); u32 surf_addr = plane_state->main.offset; int scaler_id = plane_state->scaler_id; @@ -3585,6 +3588,9 @@ static void skylake_update_primary_plane(struct drm_plane *plane, int dst_y = plane_state->dst.y1; int dst_w = drm_rect_width(&plane_state->dst); int dst_h = drm_rect_height(&plane_state->dst); + unsigned long aux_dist = 0; + u32 aux_x_offset = 0, aux_y_offset = 0, aux_stride = 0; + u32 tile_row_adjustment = 0; plane_ctl = PLANE_CTL_ENABLE | PLANE_CTL_PIPE_GAMMA_ENABLE | @@ -3604,10 +3610,43 @@ static void skylake_update_primary_plane(struct drm_plane *plane, intel_crtc->adjusted_x = src_x; intel_crtc->adjusted_y = src_y; + render_comp = plane_state->render_comp_enable; + if (render_comp) { + u32 tile_height = PAGE_SIZE / + intel_fb_stride_alignment(dev_priv, fb->modifier[0], + fb->pixel_format); + + u32 height_in_mem = (fb->offsets[1]/fb->pitches[0]); + tile_row_adjustment = height_in_mem % tile_height; + aux_dist = (fb->pitches[0] * + (height_in_mem - tile_row_adjustment)); + aux_stride = skl_plane_stride(fb, 1, rotation); + plane_ctl |= PLANE_CTL_DECOMPRESSION_ENABLE; + } else { + plane_ctl &= ~PLANE_CTL_DECOMPRESSION_ENABLE; + } + I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_x); I915_WRITE(PLANE_STRIDE(pipe, 0), stride); I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w); + I915_WRITE(PLANE_AUX_DIST(pipe, 0), aux_dist | aux_stride); + I915_WRITE(PLANE_AUX_OFFSET(pipe, 0), aux_y_offset<<16 | aux_x_offset); + + /* + * Per bspec, for SKL C and BXT A steppings, when the plane source pixel + * format is NV12, the CHICKEN_PIPESL register bit 22 must be set to 1. + * When render compression is enabled, bit 22 must be set to 0. + */ + if (IS_SKL_REVID(dev, 0, SKL_REVID_C0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { + u32 temp = I915_READ(CHICKEN_PIPESL_1(pipe)); + if (render_comp) { + if ((temp & HSW_FBCQ_DIS) == HSW_FBCQ_DIS) + I915_WRITE(CHICKEN_PIPESL_1(pipe), + temp & ~HSW_FBCQ_DIS); + } + } if (scaler_id >= 0) { uint32_t ps_ctrl = 0; @@ -12333,6 +12372,17 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, to_intel_plane_state(plane_state)); if (ret) return ret; + + if (fb && to_intel_plane_state(plane_state)-> + render_comp_enable) { + ret = skl_check_compression(dev, + to_intel_plane_state(plane_state), + intel_crtc->pipe, crtc->x, crtc->y); + if (ret) { + DRM_DEBUG_KMS("Render compr checks failed\n"); + return ret; + } + } } was_visible = old_plane_state->visible; @@ -12388,7 +12438,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, case DRM_PLANE_TYPE_PRIMARY: intel_crtc->atomic.post_enable_primary = turn_on; intel_crtc->atomic.update_fbc = true; - break; case DRM_PLANE_TYPE_CURSOR: break; @@ -12516,6 +12565,41 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, } } + /* + * On SKL:*:C and BXT:*:A, there is a possible hang with NV12 format. + * WA: render decompression must not be enabled on any of the planes in + * that pipe. + */ + if (IS_SKL_REVID(dev, 0, SKL_REVID_C0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { + struct drm_plane *p; + bool rc_enabled = false, nv12_enabled = false; + + drm_for_each_plane_mask(p, dev, crtc_state->plane_mask) { + struct drm_plane_state *plane_state = + drm_atomic_get_plane_state(state, p); + + if (plane_state) { + if (to_intel_plane_state(plane_state)-> + render_comp_enable) + rc_enabled = true; + + if (plane_state->fb && + plane_state->fb->pixel_format == + DRM_FORMAT_NV12) + nv12_enabled = true; + } + + } + if (rc_enabled && nv12_enabled) { + DRM_DEBUG_KMS("RC should not be enabled " + "on any plane of the " + "pipe on which NV12 is " + "enabled\n"); + return -EINVAL; + } + } + if (INTEL_INFO(dev)->gen >= 9) { if (mode_changed) ret = skl_update_scaler_crtc(pipe_config); @@ -14517,6 +14601,91 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state return max_scale; } +static int skl_check_compression(struct drm_device *dev, + struct intel_plane_state *plane_state, + enum pipe pipe, int x, int y) +{ + struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_plane *plane = plane_state->base.plane; + int x_offset; + int src_w = drm_rect_width(&plane_state->src) >> 16; + + if (!IS_SKYLAKE(dev) && !IS_BROXTON(dev)) { + DRM_DEBUG_KMS("RC support on CNL+ needs to be revisited\n"); + return -EINVAL; + } + + /* + * 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_SKL_REVID(dev, 0, SKL_REVID_C0) && ((src_w < 32) || (src_w > 2048))) { + DRM_DEBUG_KMS("SKL-A, SKL-B RC: width > 2048 or < 32\n"); + 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) { + DRM_DEBUG_KMS("RC supported only on pipe A & B\n"); + return -EINVAL; + } + + if (!(plane->type == DRM_PLANE_TYPE_PRIMARY || + (plane->type == DRM_PLANE_TYPE_OVERLAY && + to_intel_plane(plane)->plane == PLANE_A))) { + DRM_DEBUG_KMS("RC supported only on planes 1 & 2\n"); + return -EINVAL; + } + + if (intel_rotation_90_or_270(plane_state->base.rotation)) { + DRM_DEBUG_KMS("RC support only with 0/180 degree rotation\n"); + return -EINVAL; + } + + if ((fb->modifier[0] == DRM_FORMAT_MOD_NONE) || + (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)) { + DRM_DEBUG_KMS("RC supported only with Y-tile\n"); + return -EINVAL; + } + + if ((fb->pixel_format != DRM_FORMAT_XBGR8888) && + (fb->pixel_format != DRM_FORMAT_ABGR8888)) { + DRM_DEBUG_KMS("RC supported only with RGB8888 formats\n"); + return -EINVAL; + } + + /* + * For SKL & 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. + */ + x_offset = x; + + if (src_w > 3840 && x_offset != 0) { + DRM_DEBUG_KMS("RC: width > 3840, horizontal panning\n"); + return -EINVAL; + } + + return 0; +} + static int intel_check_primary_plane(struct drm_plane *plane, struct intel_crtc_state *crtc_state, @@ -14679,6 +14848,9 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, if (INTEL_INFO(dev)->gen >= 4) intel_create_rotation_property(dev, primary); + if (INTEL_INFO(dev)->gen >= 9) + intel_create_render_comp_property(dev, primary); + drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); return &primary->base; @@ -14702,6 +14874,36 @@ void intel_create_rotation_property(struct drm_device *dev, struct intel_plane * plane->base.state->rotation); } +void intel_create_render_comp_property(struct drm_device *dev, + struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + static const struct drm_prop_enum_list rc_status[] = { + { COMP_UNCOMPRESSED, "Uncompressed/not capable" }, + { COMP_RENDER, "Only render decompression" }, + }; + + if (!dev_priv->render_comp_property) { + dev_priv->render_comp_property = + drm_property_create_bitmask(dev, 0, + "render compression", + rc_status, ARRAY_SIZE(rc_status), + BIT(COMP_UNCOMPRESSED) | + BIT(COMP_RENDER)); + if (!dev_priv->render_comp_property) { + DRM_ERROR("RC: Failed to create property\n"); + return; + } + } + + if (dev_priv->render_comp_property) { + drm_object_attach_property(&plane->base.base, + dev_priv->render_comp_property, 0); + } + dev->mode_config.allow_aux_plane = true; +} + static int intel_check_cursor_plane(struct drm_plane *plane, struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 68dd7ac..3158d9f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -154,7 +154,7 @@ struct intel_framebuffer { struct drm_i915_gem_object *obj; struct intel_rotation_info rot_info; - /* for each plane in the normal GTT view */ + /* for each plane in the normal GTT view */ struct { unsigned int x, y; } normal[2]; @@ -313,6 +313,10 @@ struct intel_atomic_state { bool skip_intermediate_wm; }; +/* render compression property bits */ +#define COMP_UNCOMPRESSED 0 +#define COMP_RENDER 1 + struct intel_plane_state { struct drm_plane_state base; struct drm_rect src; @@ -352,6 +356,9 @@ struct intel_plane_state { /* async flip related structures */ struct drm_i915_gem_request *wait_req; + + /* Render compression */ + unsigned int render_comp_enable; }; struct intel_initial_plane_config { @@ -1135,11 +1142,11 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); /* intel_display.c */ extern const struct drm_plane_funcs intel_plane_funcs; -unsigned int intel_fb_xy_to_linear(int x, int y, - const struct intel_plane_state *state, - int plane); -void intel_add_fb_offsets(int *x, int *y, - const struct intel_plane_state *state, int plane); +unsigned int intel_fb_xy_to_linear(int x, int y, + const struct intel_plane_state *state, + int plane); +void intel_add_fb_offsets(int *x, int *y, + const struct intel_plane_state *state, int plane); unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info); bool intel_has_pending_fb_unpin(struct drm_device *dev); void intel_mark_busy(struct drm_device *dev); @@ -1223,6 +1230,9 @@ intel_rotation_90_or_270(unsigned int rotation) void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane); +void intel_create_render_comp_property(struct drm_device *dev, + struct intel_plane *plane); + /* 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, @@ -1252,7 +1262,7 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) -u32 intel_compute_tile_offset(int *x, int *y, +u32 intel_compute_tile_offset(int *x, int *y, const struct intel_plane_state *state, int plane); void intel_prepare_reset(struct drm_device *dev); void intel_finish_reset(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 75bf01d..bb6bbde 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -191,7 +191,7 @@ skl_update_plane(struct drm_plane *drm_plane, u32 plane_ctl; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 surf_addr = plane_state->main.offset; - unsigned int rotation = plane_state->base.rotation; + unsigned int rotation = plane_state->base.rotation, render_comp; u32 stride = skl_plane_stride(fb, 0, rotation); int crtc_x = plane_state->dst.x1; int crtc_y = plane_state->dst.y1; @@ -203,6 +203,9 @@ skl_update_plane(struct drm_plane *drm_plane, uint32_t src_h = drm_rect_height(&plane_state->src) >> 16; const struct intel_scaler *scaler = &crtc_state->scaler_state.scalers[plane_state->scaler_id]; + unsigned long aux_dist = 0; + u32 aux_x_offset = 0, aux_y_offset = 0, aux_stride = 0; + u32 tile_row_adjustment = 0; plane_ctl = PLANE_CTL_ENABLE | PLANE_CTL_PIPE_GAMMA_ENABLE | @@ -230,9 +233,43 @@ skl_update_plane(struct drm_plane *drm_plane, crtc_w--; crtc_h--; + render_comp = plane_state->render_comp_enable; + if (render_comp) { + u32 tile_height = PAGE_SIZE / + intel_fb_stride_alignment(dev_priv, fb->modifier[0], + fb->pixel_format); + + u32 height_in_mem = (fb->offsets[1]/fb->pitches[0]); + tile_row_adjustment = height_in_mem % tile_height; + aux_dist = (fb->pitches[0] * + (height_in_mem - tile_row_adjustment)); + aux_stride = skl_plane_stride(fb, 1, rotation); + plane_ctl |= PLANE_CTL_DECOMPRESSION_ENABLE; + } else { + plane_ctl &= ~PLANE_CTL_DECOMPRESSION_ENABLE; + } + I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x); I915_WRITE(PLANE_STRIDE(pipe, plane), stride); I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w); + I915_WRITE(PLANE_AUX_DIST(pipe, plane), aux_dist | aux_stride); + I915_WRITE(PLANE_AUX_OFFSET(pipe, plane), + aux_y_offset<<16 | aux_x_offset); + + /* + * Per bspec, for SKL C and BXT A steppings, when the plane source pixel + * format is NV12, the CHICKEN_PIPESL register bit 22 must be set to 1. + * When render compression is enabled, bit 22 must be set to 0. + */ + if (IS_SKL_REVID(dev, 0, SKL_REVID_C0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { + u32 temp = I915_READ(CHICKEN_PIPESL_1(pipe)); + if (render_comp) { + if ((temp & HSW_FBCQ_DIS) == HSW_FBCQ_DIS) + I915_WRITE(CHICKEN_PIPESL_1(pipe), + temp & ~HSW_FBCQ_DIS); + } + } /* program plane scaler */ if (plane_state->scaler_id >= 0) { @@ -1092,6 +1129,9 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_create_rotation_property(dev, intel_plane); + if (INTEL_INFO(dev)->gen >= 9) + intel_create_render_comp_property(dev, intel_plane); + drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); out: -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx