Message ID | 20180719182214.4323-11-ville.syrjala@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, 2018-07-19 at 21:22 +0300, Ville Syrjala wrote: > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > Split up intel_check_primary_plane() and intel_check_sprite_plane() > into per-platform variants. This way we can get a unified behaviour > between the SKL universal planes, and we stop checking for non-SKL > specific scaling limits for the "sprite" planes. And we now get > a natural place where to add more plarform specific checks. > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > --- > drivers/gpu/drm/i915/intel_atomic_plane.c | 2 +- > drivers/gpu/drm/i915/intel_display.c | 123 +++++------- > drivers/gpu/drm/i915/intel_drv.h | 13 +- > drivers/gpu/drm/i915/intel_sprite.c | 303 +++++++++++++++++++- > ---------- > 4 files changed, 249 insertions(+), 192 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c > b/drivers/gpu/drm/i915/intel_atomic_plane.c > index dcba645cabb8..eddcdd6e4b3b 100644 > --- a/drivers/gpu/drm/i915/intel_atomic_plane.c > +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c > @@ -159,7 +159,7 @@ int intel_plane_atomic_check_with_state(const > struct intel_crtc_state *old_crtc_ > } > > intel_state->base.visible = false; > - ret = intel_plane->check_plane(intel_plane, crtc_state, > intel_state); > + ret = intel_plane->check_plane(crtc_state, intel_state); > if (ret) > return ret; > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index fdc5bedc5135..9b9eaeda15dd 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -3350,6 +3350,36 @@ int i9xx_check_plane_surface(struct > intel_plane_state *plane_state) > return 0; > } > > +static int > +i9xx_plane_check(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state) > +{ > + int ret; > + > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > + &crtc_state->base, > + DRM_PLANE_HELPER_NO_S > CALING, > + DRM_PLANE_HELPER_NO_S > CALING, > + false, true); > + if (ret) > + return ret; > + > + if (!plane_state->base.visible) > + return 0; > + > + ret = intel_plane_check_src_coordinates(plane_state); > + if (ret) > + return ret; > + > + ret = i9xx_check_plane_surface(plane_state); > + if (ret) > + return ret; > + > + plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); > + > + return 0; > +} > + > static void i9xx_update_plane(struct intel_plane *plane, > const struct intel_crtc_state > *crtc_state, > const struct intel_plane_state > *plane_state) > @@ -9680,6 +9710,11 @@ static int intel_check_cursor(struct > intel_crtc_state *crtc_state, > u32 offset; > int ret; > > + if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { > + DRM_DEBUG_KMS("cursor cannot be tiled\n"); > + return -EINVAL; > + } > + > ret = drm_atomic_helper_check_plane_state(&plane_state->base, > &crtc_state->base, > DRM_PLANE_HELPER_NO_S > CALING, > @@ -9688,13 +9723,12 @@ static int intel_check_cursor(struct > intel_crtc_state *crtc_state, > if (ret) > return ret; > > - if (!fb) > + if (!plane_state->base.visible) > return 0; > > - if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { > - DRM_DEBUG_KMS("cursor cannot be tiled\n"); > - return -EINVAL; > - } > + ret = intel_plane_check_src_coordinates(plane_state); > + if (ret) > + return ret; > > intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); > plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, > rotation); > @@ -9744,8 +9778,7 @@ static bool i845_cursor_size_ok(const struct > intel_plane_state *plane_state) > return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, > 64); > } > > -static int i845_check_cursor(struct intel_plane *plane, > - struct intel_crtc_state *crtc_state, > +static int i845_check_cursor(struct intel_crtc_state *crtc_state, > struct intel_plane_state *plane_state) You are dropping struct intel_plane *plane from check_plane and in skl_max_scale(), I think it is a good thing to do but would be better do it in a previous patch and leave this one just extracting check_plane(). > { > const struct drm_framebuffer *fb = plane_state->base.fb; > @@ -9943,10 +9976,10 @@ static bool i9xx_cursor_size_ok(const struct > intel_plane_state *plane_state) > return true; > } > > -static int i9xx_check_cursor(struct intel_plane *plane, > - struct intel_crtc_state *crtc_state, > +static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, > struct intel_plane_state *plane_state) > { > + struct intel_plane *plane = to_intel_plane(plane_state- > >base.plane); > struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > const struct drm_framebuffer *fb = plane_state->base.fb; > enum pipe pipe = plane->pipe; > @@ -13193,19 +13226,17 @@ intel_cleanup_plane_fb(struct drm_plane > *plane, > } > > int > -skl_max_scale(struct intel_crtc *intel_crtc, > - struct intel_crtc_state *crtc_state, > - uint32_t pixel_format) > +skl_max_scale(const struct intel_crtc_state *crtc_state, > + u32 pixel_format) > { > - struct drm_i915_private *dev_priv; > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > int max_scale, mult; > int crtc_clock, max_dotclk, tmpclk1, tmpclk2; > > - if (!intel_crtc || !crtc_state->base.enable) > + if (!crtc_state->base.enable) > return DRM_PLANE_HELPER_NO_SCALING; > > - dev_priv = to_i915(intel_crtc->base.dev); > - > crtc_clock = crtc_state->base.adjusted_mode.crtc_clock; > max_dotclk = to_intel_atomic_state(crtc_state->base.state)- > >cdclk.logical.cdclk; > > @@ -13229,61 +13260,6 @@ skl_max_scale(struct intel_crtc *intel_crtc, > return max_scale; > } > > -static int > -intel_check_primary_plane(struct intel_plane *plane, > - struct intel_crtc_state *crtc_state, > - struct intel_plane_state *state) > -{ > - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > - struct drm_crtc *crtc = state->base.crtc; > - int min_scale = DRM_PLANE_HELPER_NO_SCALING; > - int max_scale = DRM_PLANE_HELPER_NO_SCALING; > - bool can_position = false; > - int ret; > - uint32_t pixel_format = 0; > - > - if (INTEL_GEN(dev_priv) >= 9) { > - /* use scaler when colorkey is not required */ > - if (!state->ckey.flags) { > - min_scale = 1; > - if (state->base.fb) > - pixel_format = state->base.fb->format- > >format; > - max_scale = skl_max_scale(to_intel_crtc(crtc), > - crtc_state, > pixel_format); > - } > - can_position = true; > - } > - > - ret = drm_atomic_helper_check_plane_state(&state->base, > - &crtc_state->base, > - min_scale, max_scale, > - can_position, true); > - if (ret) > - return ret; > - > - if (!state->base.fb) > - return 0; > - > - if (INTEL_GEN(dev_priv) >= 9) { > - ret = skl_check_plane_surface(crtc_state, state); > - if (ret) > - return ret; > - > - state->ctl = skl_plane_ctl(crtc_state, state); > - } else { > - ret = i9xx_check_plane_surface(state); > - if (ret) > - return ret; > - > - state->ctl = i9xx_plane_ctl(crtc_state, state); > - } > - > - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) > - state->color_ctl = glk_plane_color_ctl(crtc_state, > state); > - > - return 0; > -} > - > static void intel_begin_crtc_commit(struct drm_crtc *crtc, > struct drm_crtc_state > *old_crtc_state) > { > @@ -13736,8 +13712,6 @@ intel_primary_plane_create(struct > drm_i915_private *dev_priv, enum pipe pipe) > fbc->possible_framebuffer_bits |= primary- > >frontbuffer_bit; > } > > - primary->check_plane = intel_check_primary_plane; > - > if (INTEL_GEN(dev_priv) >= 9) { > primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe, > PLANE_PRIMARY); > @@ -13759,6 +13733,7 @@ intel_primary_plane_create(struct > drm_i915_private *dev_priv, enum pipe pipe) > primary->update_plane = skl_update_plane; > primary->disable_plane = skl_disable_plane; > primary->get_hw_state = skl_plane_get_hw_state; > + primary->check_plane = skl_plane_check; > > plane_funcs = &skl_plane_funcs; > } else if (INTEL_GEN(dev_priv) >= 4) { > @@ -13770,6 +13745,7 @@ intel_primary_plane_create(struct > drm_i915_private *dev_priv, enum pipe pipe) > primary->update_plane = i9xx_update_plane; > primary->disable_plane = i9xx_disable_plane; > primary->get_hw_state = i9xx_plane_get_hw_state; > + primary->check_plane = i9xx_plane_check; > > plane_funcs = &i965_plane_funcs; > } else { > @@ -13781,6 +13757,7 @@ intel_primary_plane_create(struct > drm_i915_private *dev_priv, enum pipe pipe) > primary->update_plane = i9xx_update_plane; > primary->disable_plane = i9xx_disable_plane; > primary->get_hw_state = i9xx_plane_get_hw_state; > + primary->check_plane = i9xx_plane_check; > > plane_funcs = &i8xx_plane_funcs; > } > diff --git a/drivers/gpu/drm/i915/intel_drv.h > b/drivers/gpu/drm/i915/intel_drv.h > index c6c782e14897..6d57c6a508d4 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -973,9 +973,8 @@ struct intel_plane { > void (*disable_plane)(struct intel_plane *plane, > struct intel_crtc *crtc); > bool (*get_hw_state)(struct intel_plane *plane, enum pipe > *pipe); > - int (*check_plane)(struct intel_plane *plane, > - struct intel_crtc_state *crtc_state, > - struct intel_plane_state *state); > + int (*check_plane)(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state); > }; > > struct intel_watermark_params { > @@ -1637,8 +1636,8 @@ void intel_crtc_arm_fifo_underrun(struct > intel_crtc *crtc, > > u16 skl_scaler_calc_phase(int sub, bool chroma_center); > int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); > -int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state > *crtc_state, > - uint32_t pixel_format); > +int skl_max_scale(const struct intel_crtc_state *crtc_state, > + u32 pixel_format); > > static inline u32 intel_plane_ggtt_offset(const struct > intel_plane_state *state) > { > @@ -2112,7 +2111,9 @@ bool skl_plane_has_planar(struct > drm_i915_private *dev_priv, > unsigned int skl_plane_max_stride(struct intel_plane *plane, > u32 pixel_format, u64 modifier, > unsigned int rotation); > - > +int skl_plane_check(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state); > +int intel_plane_check_src_coordinates(struct intel_plane_state > *plane_state); > > /* intel_tv.c */ > void intel_tv_init(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 0d3931b8a981..36e150885897 100644 > --- a/drivers/gpu/drm/i915/intel_sprite.c > +++ b/drivers/gpu/drm/i915/intel_sprite.c > @@ -228,6 +228,39 @@ void intel_pipe_update_end(struct > intel_crtc_state *new_crtc_state) > #endif > } > > +int intel_plane_check_src_coordinates(struct intel_plane_state > *plane_state) > +{ > + const struct drm_framebuffer *fb = plane_state->base.fb; > + struct drm_rect *src = &plane_state->base.src; > + u32 src_x, src_y, src_w, src_h; > + > + /* > + * Hardware doesn't handle subpixel coordinates. > + * Adjust to (macro)pixel boundary, but be careful not to > + * increase the source viewport size, because that could > + * push the downscaling factor out of bounds. > + */ > + src_x = src->x1 >> 16; > + src_w = drm_rect_width(src) >> 16; > + src_y = src->y1 >> 16; > + src_h = drm_rect_height(src) >> 16; > + > + src->x1 = src_x << 16; > + src->x2 = (src_x + src_w) << 16; > + src->y1 = src_y << 16; > + src->y2 = (src_y + src_h) << 16; > + > + if (fb->format->is_yuv && > + fb->format->format != DRM_FORMAT_NV12 && > + (src_x & 1 || src_w & 1)) { > + DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 > for YUV planes\n", > + src_x, src_w); > + return -EINVAL; > + } > + > + return 0; > +} > + > unsigned int > skl_plane_max_stride(struct intel_plane *plane, > u32 pixel_format, u64 modifier, > @@ -983,146 +1016,189 @@ g4x_plane_get_hw_state(struct intel_plane > *plane, > } > > static int > -intel_check_sprite_plane(struct intel_plane *plane, > - struct intel_crtc_state *crtc_state, > - struct intel_plane_state *state) > +g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state) > { > - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > - struct drm_framebuffer *fb = state->base.fb; > - int max_scale, min_scale; > - int ret; > - uint32_t pixel_format = 0; > - > - if (!fb) { > - state->base.visible = false; > + const struct drm_framebuffer *fb = plane_state->base.fb; > + const struct drm_rect *src = &plane_state->base.src; > + const struct drm_rect *dst = &plane_state->base.dst; > + int src_x, src_y, src_w, src_h, crtc_w, crtc_h; > + const struct drm_display_mode *adjusted_mode = > + &crtc_state->base.adjusted_mode; > + unsigned int cpp = fb->format->cpp[0]; > + unsigned int width_bytes; > + int min_width, min_height; > + > + crtc_w = drm_rect_width(dst); > + crtc_h = drm_rect_height(dst); > + > + src_x = src->x1 >> 16; > + src_y = src->y1 >> 16; > + src_w = drm_rect_width(src) >> 16; > + src_h = drm_rect_height(src) >> 16; > + > + if (src_w == crtc_w && src_h == crtc_h) > return 0; > + > + min_width = 3; > + > + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { > + if (src_h & 1) { > + DRM_DEBUG_KMS("Source height must be even with > interlaced modes\n"); > + return -EINVAL; > + } > + min_height = 6; > + } else { > + min_height = 3; > } > > - /* Don't modify another pipe's plane */ > - if (plane->pipe != crtc->pipe) { > - DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); > + width_bytes = ((src_x * cpp) & 63) + src_w * cpp; > + > + if (src_w < min_width || src_h < min_height || > + src_w > 2048 || src_h > 2048) { > + DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed > hardware limits (%dx%d - %dx%d)\n", > + src_w, src_h, min_width, min_height, > 2048, 2048); > return -EINVAL; > } > > - /* FIXME check all gen limits */ > - if (fb->width < 3 || fb->height < 3 || > - fb->pitches[0] > plane->max_stride(plane, fb->format- > >format, > - fb->modifier, > DRM_MODE_ROTATE_0)) { > - DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); > + if (width_bytes > 4096) { > + DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max > with scaling (%u)\n", > + width_bytes, 4096); > return -EINVAL; > } > > - if (INTEL_GEN(dev_priv) >= 9) { > - if (state->base.fb) > - pixel_format = state->base.fb->format->format; > - /* use scaler when colorkey is not required */ > - if (!state->ckey.flags) { > - min_scale = 1; > - max_scale = > - skl_max_scale(crtc, crtc_state, > pixel_format); > - } else { > - min_scale = DRM_PLANE_HELPER_NO_SCALING; > - max_scale = DRM_PLANE_HELPER_NO_SCALING; > - } > + if (width_bytes > 4096 || fb->pitches[0] > 4096) { > + DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with > scaling (%u)\n", > + fb->pitches[0], 4096); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int > +g4x_sprite_check(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state) > +{ > + struct intel_plane *plane = to_intel_plane(plane_state- > >base.plane); > + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > + int max_scale, min_scale; > + int ret; > + > + if (INTEL_GEN(dev_priv) < 7) { > + min_scale = 1; > + max_scale = 16 << 16; > + } else if (IS_IVYBRIDGE(dev_priv)) { > + min_scale = 1; > + max_scale = 2 << 16; > } else { > - if (INTEL_GEN(dev_priv) < 7) { > - min_scale = 1; > - max_scale = 16 << 16; > - } else if (IS_IVYBRIDGE(dev_priv)) { > - min_scale = 1; > - max_scale = 2 << 16; > - } else { > - min_scale = DRM_PLANE_HELPER_NO_SCALING; > - max_scale = DRM_PLANE_HELPER_NO_SCALING; > - } > + min_scale = DRM_PLANE_HELPER_NO_SCALING; > + max_scale = DRM_PLANE_HELPER_NO_SCALING; > } > > - ret = drm_atomic_helper_check_plane_state(&state->base, > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > &crtc_state->base, > min_scale, max_scale, > true, true); > if (ret) > return ret; > > - if (state->base.visible) { > - struct drm_rect *src = &state->base.src; > - struct drm_rect *dst = &state->base.dst; > - unsigned int crtc_w = drm_rect_width(dst); > - unsigned int crtc_h = drm_rect_height(dst); > - uint32_t src_x, src_y, src_w, src_h; > + if (!plane_state->base.visible) > + return 0; > > - /* > - * Hardware doesn't handle subpixel coordinates. > - * Adjust to (macro)pixel boundary, but be careful not > to > - * increase the source viewport size, because that > could > - * push the downscaling factor out of bounds. > - */ > - src_x = src->x1 >> 16; > - src_w = drm_rect_width(src) >> 16; > - src_y = src->y1 >> 16; > - src_h = drm_rect_height(src) >> 16; > - > - src->x1 = src_x << 16; > - src->x2 = (src_x + src_w) << 16; > - src->y1 = src_y << 16; > - src->y2 = (src_y + src_h) << 16; > - > - if (fb->format->is_yuv && > - fb->format->format != DRM_FORMAT_NV12 && > - (src_x % 2 || src_w % 2)) { > - DRM_DEBUG_KMS("src x/w (%u, %u) must be a > multiple of 2 for YUV planes\n", > - src_x, src_w); > - return -EINVAL; > - } > + ret = intel_plane_check_src_coordinates(plane_state); > + if (ret) > + return ret; > > - /* Check size restrictions when scaling */ > - if (src_w != crtc_w || src_h != crtc_h) { > - unsigned int width_bytes; > - int cpp = fb->format->cpp[0]; > - > - width_bytes = ((src_x * cpp) & 63) + src_w * > cpp; > - > - /* FIXME interlacing min height is 6 */ > - if (INTEL_GEN(dev_priv) < 9 && ( > - src_w < 3 || src_h < 3 || > - src_w > 2048 || src_h > 2048 || > - crtc_w < 3 || crtc_h < 3 || > - width_bytes > 4096 || fb->pitches[0] > > 4096)) { > - DRM_DEBUG_KMS("Source dimensions exceed > hardware limits\n"); > - return -EINVAL; > - } > - } > - } > + ret = g4x_sprite_check_scaling(crtc_state, plane_state); > + if (ret) > + return ret; > > - if (INTEL_GEN(dev_priv) >= 9) { > - ret = skl_check_plane_surface(crtc_state, state); > - if (ret) > - return ret; > + ret = i9xx_check_plane_surface(plane_state); > + if (ret) > + return ret; > > - state->ctl = skl_plane_ctl(crtc_state, state); > - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) > { > - ret = i9xx_check_plane_surface(state); > - if (ret) > - return ret; > + if (INTEL_GEN(dev_priv) >= 7) > + plane_state->ctl = ivb_sprite_ctl(crtc_state, > plane_state); > + else > + plane_state->ctl = g4x_sprite_ctl(crtc_state, > plane_state); > > - state->ctl = vlv_sprite_ctl(crtc_state, state); > - } else if (INTEL_GEN(dev_priv) >= 7) { > - ret = i9xx_check_plane_surface(state); > - if (ret) > - return ret; > + return 0; > +} > > - state->ctl = ivb_sprite_ctl(crtc_state, state); > - } else { > - ret = i9xx_check_plane_surface(state); > - if (ret) > - return ret; > +static int > +vlv_sprite_check(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state) > +{ > + int ret; > + > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > + &crtc_state->base, > + DRM_PLANE_HELPER_NO_S > CALING, > + DRM_PLANE_HELPER_NO_S > CALING, > + true, true); > + if (ret) > + return ret; > + > + if (!plane_state->base.visible) > + return 0; > + > + ret = intel_plane_check_src_coordinates(plane_state); > + if (ret) > + return ret; Looks like it is missing a g4x_sprite_check_scaling() call for VLV/CHV. Other than the 2 comments above: Reviewed-by: José Roberto de Souza <jose.souza@intel.com> > + > + ret = i9xx_check_plane_surface(plane_state); > + if (ret) > + return ret; > + > + plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state); > > - state->ctl = g4x_sprite_ctl(crtc_state, state); > + return 0; > +} > + > +int skl_plane_check(struct intel_crtc_state *crtc_state, > + struct intel_plane_state *plane_state) > +{ > + struct intel_plane *plane = to_intel_plane(plane_state- > >base.plane); > + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > + int max_scale, min_scale; > + int ret; > + > + /* use scaler when colorkey is not required */ > + if (!plane_state->ckey.flags) { > + const struct drm_framebuffer *fb = plane_state- > >base.fb; > + > + min_scale = 1; > + max_scale = skl_max_scale(crtc_state, > + fb ? fb->format->format : 0); > + } else { > + min_scale = DRM_PLANE_HELPER_NO_SCALING; > + max_scale = DRM_PLANE_HELPER_NO_SCALING; > } > > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > + &crtc_state->base, > + min_scale, max_scale, > + true, true); > + if (ret) > + return ret; > + > + if (!plane_state->base.visible) > + return 0; > + > + ret = intel_plane_check_src_coordinates(plane_state); > + if (ret) > + return ret; > + > + ret = skl_check_plane_surface(crtc_state, plane_state); > + if (ret) > + return ret; > + > + plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); > + > if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) > - state->color_ctl = glk_plane_color_ctl(crtc_state, > state); > + plane_state->color_ctl = > glk_plane_color_ctl(crtc_state, > + plane_stat > e); > > return 0; > } > @@ -1559,6 +1635,7 @@ intel_sprite_plane_create(struct > drm_i915_private *dev_priv, > intel_plane->update_plane = skl_update_plane; > intel_plane->disable_plane = skl_disable_plane; > intel_plane->get_hw_state = skl_plane_get_hw_state; > + intel_plane->check_plane = skl_plane_check; > > if (skl_plane_has_planar(dev_priv, pipe, > PLANE_SPRITE0 + plane)) { > @@ -1580,6 +1657,7 @@ intel_sprite_plane_create(struct > drm_i915_private *dev_priv, > intel_plane->update_plane = vlv_update_plane; > intel_plane->disable_plane = vlv_disable_plane; > intel_plane->get_hw_state = vlv_plane_get_hw_state; > + intel_plane->check_plane = vlv_sprite_check; > > plane_formats = vlv_plane_formats; > num_plane_formats = ARRAY_SIZE(vlv_plane_formats); > @@ -1591,6 +1669,7 @@ intel_sprite_plane_create(struct > drm_i915_private *dev_priv, > intel_plane->update_plane = ivb_update_plane; > intel_plane->disable_plane = ivb_disable_plane; > intel_plane->get_hw_state = ivb_plane_get_hw_state; > + intel_plane->check_plane = g4x_sprite_check; > > plane_formats = snb_plane_formats; > num_plane_formats = ARRAY_SIZE(snb_plane_formats); > @@ -1602,6 +1681,7 @@ intel_sprite_plane_create(struct > drm_i915_private *dev_priv, > intel_plane->update_plane = g4x_update_plane; > intel_plane->disable_plane = g4x_disable_plane; > intel_plane->get_hw_state = g4x_plane_get_hw_state; > + intel_plane->check_plane = g4x_sprite_check; > > modifiers = i9xx_plane_format_modifiers; > if (IS_GEN6(dev_priv)) { > @@ -1634,7 +1714,6 @@ intel_sprite_plane_create(struct > drm_i915_private *dev_priv, > intel_plane->i9xx_plane = plane; > intel_plane->id = PLANE_SPRITE0 + plane; > intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, > intel_plane->id); > - intel_plane->check_plane = intel_check_sprite_plane; > > possible_crtcs = (1 << pipe); >
On Fri, Aug 24, 2018 at 01:01:36AM +0000, Souza, Jose wrote: > On Thu, 2018-07-19 at 21:22 +0300, Ville Syrjala wrote: > > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > > > Split up intel_check_primary_plane() and intel_check_sprite_plane() > > into per-platform variants. This way we can get a unified behaviour > > between the SKL universal planes, and we stop checking for non-SKL > > specific scaling limits for the "sprite" planes. And we now get > > a natural place where to add more plarform specific checks. > > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > > --- > > drivers/gpu/drm/i915/intel_atomic_plane.c | 2 +- > > drivers/gpu/drm/i915/intel_display.c | 123 +++++------- > > drivers/gpu/drm/i915/intel_drv.h | 13 +- > > drivers/gpu/drm/i915/intel_sprite.c | 303 +++++++++++++++++++- > > ---------- > > 4 files changed, 249 insertions(+), 192 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c > > b/drivers/gpu/drm/i915/intel_atomic_plane.c > > index dcba645cabb8..eddcdd6e4b3b 100644 > > --- a/drivers/gpu/drm/i915/intel_atomic_plane.c > > +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c > > @@ -159,7 +159,7 @@ int intel_plane_atomic_check_with_state(const > > struct intel_crtc_state *old_crtc_ > > } > > > > intel_state->base.visible = false; > > - ret = intel_plane->check_plane(intel_plane, crtc_state, > > intel_state); > > + ret = intel_plane->check_plane(crtc_state, intel_state); > > if (ret) > > return ret; > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c > > b/drivers/gpu/drm/i915/intel_display.c > > index fdc5bedc5135..9b9eaeda15dd 100644 > > --- a/drivers/gpu/drm/i915/intel_display.c > > +++ b/drivers/gpu/drm/i915/intel_display.c > > @@ -3350,6 +3350,36 @@ int i9xx_check_plane_surface(struct > > intel_plane_state *plane_state) > > return 0; > > } > > > > +static int > > +i9xx_plane_check(struct intel_crtc_state *crtc_state, > > + struct intel_plane_state *plane_state) > > +{ > > + int ret; > > + > > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > > + &crtc_state->base, > > + DRM_PLANE_HELPER_NO_S > > CALING, > > + DRM_PLANE_HELPER_NO_S > > CALING, > > + false, true); > > + if (ret) > > + return ret; > > + > > + if (!plane_state->base.visible) > > + return 0; > > + > > + ret = intel_plane_check_src_coordinates(plane_state); > > + if (ret) > > + return ret; > > + > > + ret = i9xx_check_plane_surface(plane_state); > > + if (ret) > > + return ret; > > + > > + plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); > > + > > + return 0; > > +} > > + > > static void i9xx_update_plane(struct intel_plane *plane, > > const struct intel_crtc_state > > *crtc_state, > > const struct intel_plane_state > > *plane_state) > > @@ -9680,6 +9710,11 @@ static int intel_check_cursor(struct > > intel_crtc_state *crtc_state, > > u32 offset; > > int ret; > > > > + if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { > > + DRM_DEBUG_KMS("cursor cannot be tiled\n"); > > + return -EINVAL; > > + } > > + > > ret = drm_atomic_helper_check_plane_state(&plane_state->base, > > &crtc_state->base, > > DRM_PLANE_HELPER_NO_S > > CALING, > > @@ -9688,13 +9723,12 @@ static int intel_check_cursor(struct > > intel_crtc_state *crtc_state, > > if (ret) > > return ret; > > > > - if (!fb) > > + if (!plane_state->base.visible) > > return 0; > > > > - if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { > > - DRM_DEBUG_KMS("cursor cannot be tiled\n"); > > - return -EINVAL; > > - } > > + ret = intel_plane_check_src_coordinates(plane_state); > > + if (ret) > > + return ret; > > > > intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); > > plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, > > rotation); > > @@ -9744,8 +9778,7 @@ static bool i845_cursor_size_ok(const struct > > intel_plane_state *plane_state) > > return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, > > 64); > > } > > > > -static int i845_check_cursor(struct intel_plane *plane, > > - struct intel_crtc_state *crtc_state, > > +static int i845_check_cursor(struct intel_crtc_state *crtc_state, > > struct intel_plane_state *plane_state) > > You are dropping struct intel_plane *plane from check_plane and in > skl_max_scale(), I think it is a good thing to do but would be better > do it in a previous patch and leave this one just extracting > check_plane(). Yeah, I can yank that out easily enough. > > > { > > const struct drm_framebuffer *fb = plane_state->base.fb; > > @@ -9943,10 +9976,10 @@ static bool i9xx_cursor_size_ok(const struct > > intel_plane_state *plane_state) > > return true; > > } > > > > -static int i9xx_check_cursor(struct intel_plane *plane, > > - struct intel_crtc_state *crtc_state, > > +static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, > > struct intel_plane_state *plane_state) > > { > > + struct intel_plane *plane = to_intel_plane(plane_state- > > >base.plane); > > struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > > const struct drm_framebuffer *fb = plane_state->base.fb; > > enum pipe pipe = plane->pipe; > > @@ -13193,19 +13226,17 @@ intel_cleanup_plane_fb(struct drm_plane > > *plane, > > } > > > > int > > -skl_max_scale(struct intel_crtc *intel_crtc, > > - struct intel_crtc_state *crtc_state, > > - uint32_t pixel_format) > > +skl_max_scale(const struct intel_crtc_state *crtc_state, > > + u32 pixel_format) > > { > > - struct drm_i915_private *dev_priv; > > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > > int max_scale, mult; > > int crtc_clock, max_dotclk, tmpclk1, tmpclk2; > > > > - if (!intel_crtc || !crtc_state->base.enable) > > + if (!crtc_state->base.enable) > > return DRM_PLANE_HELPER_NO_SCALING; > > > > - dev_priv = to_i915(intel_crtc->base.dev); > > - > > crtc_clock = crtc_state->base.adjusted_mode.crtc_clock; > > max_dotclk = to_intel_atomic_state(crtc_state->base.state)- > > >cdclk.logical.cdclk; > > > > @@ -13229,61 +13260,6 @@ skl_max_scale(struct intel_crtc *intel_crtc, > > return max_scale; > > } > > > > -static int > > -intel_check_primary_plane(struct intel_plane *plane, > > - struct intel_crtc_state *crtc_state, > > - struct intel_plane_state *state) > > -{ > > - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > > - struct drm_crtc *crtc = state->base.crtc; > > - int min_scale = DRM_PLANE_HELPER_NO_SCALING; > > - int max_scale = DRM_PLANE_HELPER_NO_SCALING; > > - bool can_position = false; > > - int ret; > > - uint32_t pixel_format = 0; > > - > > - if (INTEL_GEN(dev_priv) >= 9) { > > - /* use scaler when colorkey is not required */ > > - if (!state->ckey.flags) { > > - min_scale = 1; > > - if (state->base.fb) > > - pixel_format = state->base.fb->format- > > >format; > > - max_scale = skl_max_scale(to_intel_crtc(crtc), > > - crtc_state, > > pixel_format); > > - } > > - can_position = true; > > - } > > - > > - ret = drm_atomic_helper_check_plane_state(&state->base, > > - &crtc_state->base, > > - min_scale, max_scale, > > - can_position, true); > > - if (ret) > > - return ret; > > - > > - if (!state->base.fb) > > - return 0; > > - > > - if (INTEL_GEN(dev_priv) >= 9) { > > - ret = skl_check_plane_surface(crtc_state, state); > > - if (ret) > > - return ret; > > - > > - state->ctl = skl_plane_ctl(crtc_state, state); > > - } else { > > - ret = i9xx_check_plane_surface(state); > > - if (ret) > > - return ret; > > - > > - state->ctl = i9xx_plane_ctl(crtc_state, state); > > - } > > - > > - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) > > - state->color_ctl = glk_plane_color_ctl(crtc_state, > > state); > > - > > - return 0; > > -} > > - > > static void intel_begin_crtc_commit(struct drm_crtc *crtc, > > struct drm_crtc_state > > *old_crtc_state) > > { > > @@ -13736,8 +13712,6 @@ intel_primary_plane_create(struct > > drm_i915_private *dev_priv, enum pipe pipe) > > fbc->possible_framebuffer_bits |= primary- > > >frontbuffer_bit; > > } > > > > - primary->check_plane = intel_check_primary_plane; > > - > > if (INTEL_GEN(dev_priv) >= 9) { > > primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe, > > PLANE_PRIMARY); > > @@ -13759,6 +13733,7 @@ intel_primary_plane_create(struct > > drm_i915_private *dev_priv, enum pipe pipe) > > primary->update_plane = skl_update_plane; > > primary->disable_plane = skl_disable_plane; > > primary->get_hw_state = skl_plane_get_hw_state; > > + primary->check_plane = skl_plane_check; > > > > plane_funcs = &skl_plane_funcs; > > } else if (INTEL_GEN(dev_priv) >= 4) { > > @@ -13770,6 +13745,7 @@ intel_primary_plane_create(struct > > drm_i915_private *dev_priv, enum pipe pipe) > > primary->update_plane = i9xx_update_plane; > > primary->disable_plane = i9xx_disable_plane; > > primary->get_hw_state = i9xx_plane_get_hw_state; > > + primary->check_plane = i9xx_plane_check; > > > > plane_funcs = &i965_plane_funcs; > > } else { > > @@ -13781,6 +13757,7 @@ intel_primary_plane_create(struct > > drm_i915_private *dev_priv, enum pipe pipe) > > primary->update_plane = i9xx_update_plane; > > primary->disable_plane = i9xx_disable_plane; > > primary->get_hw_state = i9xx_plane_get_hw_state; > > + primary->check_plane = i9xx_plane_check; > > > > plane_funcs = &i8xx_plane_funcs; > > } > > diff --git a/drivers/gpu/drm/i915/intel_drv.h > > b/drivers/gpu/drm/i915/intel_drv.h > > index c6c782e14897..6d57c6a508d4 100644 > > --- a/drivers/gpu/drm/i915/intel_drv.h > > +++ b/drivers/gpu/drm/i915/intel_drv.h > > @@ -973,9 +973,8 @@ struct intel_plane { > > void (*disable_plane)(struct intel_plane *plane, > > struct intel_crtc *crtc); > > bool (*get_hw_state)(struct intel_plane *plane, enum pipe > > *pipe); > > - int (*check_plane)(struct intel_plane *plane, > > - struct intel_crtc_state *crtc_state, > > - struct intel_plane_state *state); > > + int (*check_plane)(struct intel_crtc_state *crtc_state, > > + struct intel_plane_state *plane_state); > > }; > > > > struct intel_watermark_params { > > @@ -1637,8 +1636,8 @@ void intel_crtc_arm_fifo_underrun(struct > > intel_crtc *crtc, > > > > u16 skl_scaler_calc_phase(int sub, bool chroma_center); > > int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); > > -int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state > > *crtc_state, > > - uint32_t pixel_format); > > +int skl_max_scale(const struct intel_crtc_state *crtc_state, > > + u32 pixel_format); > > > > static inline u32 intel_plane_ggtt_offset(const struct > > intel_plane_state *state) > > { > > @@ -2112,7 +2111,9 @@ bool skl_plane_has_planar(struct > > drm_i915_private *dev_priv, > > unsigned int skl_plane_max_stride(struct intel_plane *plane, > > u32 pixel_format, u64 modifier, > > unsigned int rotation); > > - > > +int skl_plane_check(struct intel_crtc_state *crtc_state, > > + struct intel_plane_state *plane_state); > > +int intel_plane_check_src_coordinates(struct intel_plane_state > > *plane_state); > > > > /* intel_tv.c */ > > void intel_tv_init(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 0d3931b8a981..36e150885897 100644 > > --- a/drivers/gpu/drm/i915/intel_sprite.c > > +++ b/drivers/gpu/drm/i915/intel_sprite.c > > @@ -228,6 +228,39 @@ void intel_pipe_update_end(struct > > intel_crtc_state *new_crtc_state) > > #endif > > } > > > > +int intel_plane_check_src_coordinates(struct intel_plane_state > > *plane_state) > > +{ > > + const struct drm_framebuffer *fb = plane_state->base.fb; > > + struct drm_rect *src = &plane_state->base.src; > > + u32 src_x, src_y, src_w, src_h; > > + > > + /* > > + * Hardware doesn't handle subpixel coordinates. > > + * Adjust to (macro)pixel boundary, but be careful not to > > + * increase the source viewport size, because that could > > + * push the downscaling factor out of bounds. > > + */ > > + src_x = src->x1 >> 16; > > + src_w = drm_rect_width(src) >> 16; > > + src_y = src->y1 >> 16; > > + src_h = drm_rect_height(src) >> 16; > > + > > + src->x1 = src_x << 16; > > + src->x2 = (src_x + src_w) << 16; > > + src->y1 = src_y << 16; > > + src->y2 = (src_y + src_h) << 16; > > + > > + if (fb->format->is_yuv && > > + fb->format->format != DRM_FORMAT_NV12 && > > + (src_x & 1 || src_w & 1)) { > > + DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 > > for YUV planes\n", > > + src_x, src_w); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > unsigned int > > skl_plane_max_stride(struct intel_plane *plane, > > u32 pixel_format, u64 modifier, > > @@ -983,146 +1016,189 @@ g4x_plane_get_hw_state(struct intel_plane > > *plane, > > } > > > > static int > > -intel_check_sprite_plane(struct intel_plane *plane, > > - struct intel_crtc_state *crtc_state, > > - struct intel_plane_state *state) > > +g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, > > + struct intel_plane_state *plane_state) > > { > > - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > > - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > > - struct drm_framebuffer *fb = state->base.fb; > > - int max_scale, min_scale; > > - int ret; > > - uint32_t pixel_format = 0; > > - > > - if (!fb) { > > - state->base.visible = false; > > + const struct drm_framebuffer *fb = plane_state->base.fb; > > + const struct drm_rect *src = &plane_state->base.src; > > + const struct drm_rect *dst = &plane_state->base.dst; > > + int src_x, src_y, src_w, src_h, crtc_w, crtc_h; > > + const struct drm_display_mode *adjusted_mode = > > + &crtc_state->base.adjusted_mode; > > + unsigned int cpp = fb->format->cpp[0]; > > + unsigned int width_bytes; > > + int min_width, min_height; > > + > > + crtc_w = drm_rect_width(dst); > > + crtc_h = drm_rect_height(dst); > > + > > + src_x = src->x1 >> 16; > > + src_y = src->y1 >> 16; > > + src_w = drm_rect_width(src) >> 16; > > + src_h = drm_rect_height(src) >> 16; > > + > > + if (src_w == crtc_w && src_h == crtc_h) > > return 0; > > + > > + min_width = 3; > > + > > + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { > > + if (src_h & 1) { > > + DRM_DEBUG_KMS("Source height must be even with > > interlaced modes\n"); > > + return -EINVAL; > > + } > > + min_height = 6; > > + } else { > > + min_height = 3; > > } > > > > - /* Don't modify another pipe's plane */ > > - if (plane->pipe != crtc->pipe) { > > - DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); > > + width_bytes = ((src_x * cpp) & 63) + src_w * cpp; > > + > > + if (src_w < min_width || src_h < min_height || > > + src_w > 2048 || src_h > 2048) { > > + DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed > > hardware limits (%dx%d - %dx%d)\n", > > + src_w, src_h, min_width, min_height, > > 2048, 2048); > > return -EINVAL; > > } > > > > - /* FIXME check all gen limits */ > > - if (fb->width < 3 || fb->height < 3 || > > - fb->pitches[0] > plane->max_stride(plane, fb->format- > > >format, > > - fb->modifier, > > DRM_MODE_ROTATE_0)) { > > - DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); > > + if (width_bytes > 4096) { > > + DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max > > with scaling (%u)\n", > > + width_bytes, 4096); > > return -EINVAL; > > } > > > > - if (INTEL_GEN(dev_priv) >= 9) { > > - if (state->base.fb) > > - pixel_format = state->base.fb->format->format; > > - /* use scaler when colorkey is not required */ > > - if (!state->ckey.flags) { > > - min_scale = 1; > > - max_scale = > > - skl_max_scale(crtc, crtc_state, > > pixel_format); > > - } else { > > - min_scale = DRM_PLANE_HELPER_NO_SCALING; > > - max_scale = DRM_PLANE_HELPER_NO_SCALING; > > - } > > + if (width_bytes > 4096 || fb->pitches[0] > 4096) { > > + DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with > > scaling (%u)\n", > > + fb->pitches[0], 4096); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int > > +g4x_sprite_check(struct intel_crtc_state *crtc_state, > > + struct intel_plane_state *plane_state) > > +{ > > + struct intel_plane *plane = to_intel_plane(plane_state- > > >base.plane); > > + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > > + int max_scale, min_scale; > > + int ret; > > + > > + if (INTEL_GEN(dev_priv) < 7) { > > + min_scale = 1; > > + max_scale = 16 << 16; > > + } else if (IS_IVYBRIDGE(dev_priv)) { > > + min_scale = 1; > > + max_scale = 2 << 16; > > } else { > > - if (INTEL_GEN(dev_priv) < 7) { > > - min_scale = 1; > > - max_scale = 16 << 16; > > - } else if (IS_IVYBRIDGE(dev_priv)) { > > - min_scale = 1; > > - max_scale = 2 << 16; > > - } else { > > - min_scale = DRM_PLANE_HELPER_NO_SCALING; > > - max_scale = DRM_PLANE_HELPER_NO_SCALING; > > - } > > + min_scale = DRM_PLANE_HELPER_NO_SCALING; > > + max_scale = DRM_PLANE_HELPER_NO_SCALING; > > } > > > > - ret = drm_atomic_helper_check_plane_state(&state->base, > > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > > &crtc_state->base, > > min_scale, max_scale, > > true, true); > > if (ret) > > return ret; > > > > - if (state->base.visible) { > > - struct drm_rect *src = &state->base.src; > > - struct drm_rect *dst = &state->base.dst; > > - unsigned int crtc_w = drm_rect_width(dst); > > - unsigned int crtc_h = drm_rect_height(dst); > > - uint32_t src_x, src_y, src_w, src_h; > > + if (!plane_state->base.visible) > > + return 0; > > > > - /* > > - * Hardware doesn't handle subpixel coordinates. > > - * Adjust to (macro)pixel boundary, but be careful not > > to > > - * increase the source viewport size, because that > > could > > - * push the downscaling factor out of bounds. > > - */ > > - src_x = src->x1 >> 16; > > - src_w = drm_rect_width(src) >> 16; > > - src_y = src->y1 >> 16; > > - src_h = drm_rect_height(src) >> 16; > > - > > - src->x1 = src_x << 16; > > - src->x2 = (src_x + src_w) << 16; > > - src->y1 = src_y << 16; > > - src->y2 = (src_y + src_h) << 16; > > - > > - if (fb->format->is_yuv && > > - fb->format->format != DRM_FORMAT_NV12 && > > - (src_x % 2 || src_w % 2)) { > > - DRM_DEBUG_KMS("src x/w (%u, %u) must be a > > multiple of 2 for YUV planes\n", > > - src_x, src_w); > > - return -EINVAL; > > - } > > + ret = intel_plane_check_src_coordinates(plane_state); > > + if (ret) > > + return ret; > > > > - /* Check size restrictions when scaling */ > > - if (src_w != crtc_w || src_h != crtc_h) { > > - unsigned int width_bytes; > > - int cpp = fb->format->cpp[0]; > > - > > - width_bytes = ((src_x * cpp) & 63) + src_w * > > cpp; > > - > > - /* FIXME interlacing min height is 6 */ > > - if (INTEL_GEN(dev_priv) < 9 && ( > > - src_w < 3 || src_h < 3 || > > - src_w > 2048 || src_h > 2048 || > > - crtc_w < 3 || crtc_h < 3 || > > - width_bytes > 4096 || fb->pitches[0] > > > 4096)) { > > - DRM_DEBUG_KMS("Source dimensions exceed > > hardware limits\n"); > > - return -EINVAL; > > - } > > - } > > - } > > + ret = g4x_sprite_check_scaling(crtc_state, plane_state); > > + if (ret) > > + return ret; > > > > - if (INTEL_GEN(dev_priv) >= 9) { > > - ret = skl_check_plane_surface(crtc_state, state); > > - if (ret) > > - return ret; > > + ret = i9xx_check_plane_surface(plane_state); > > + if (ret) > > + return ret; > > > > - state->ctl = skl_plane_ctl(crtc_state, state); > > - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) > > { > > - ret = i9xx_check_plane_surface(state); > > - if (ret) > > - return ret; > > + if (INTEL_GEN(dev_priv) >= 7) > > + plane_state->ctl = ivb_sprite_ctl(crtc_state, > > plane_state); > > + else > > + plane_state->ctl = g4x_sprite_ctl(crtc_state, > > plane_state); > > > > - state->ctl = vlv_sprite_ctl(crtc_state, state); > > - } else if (INTEL_GEN(dev_priv) >= 7) { > > - ret = i9xx_check_plane_surface(state); > > - if (ret) > > - return ret; > > + return 0; > > +} > > > > - state->ctl = ivb_sprite_ctl(crtc_state, state); > > - } else { > > - ret = i9xx_check_plane_surface(state); > > - if (ret) > > - return ret; > > +static int > > +vlv_sprite_check(struct intel_crtc_state *crtc_state, > > + struct intel_plane_state *plane_state) > > +{ > > + int ret; > > + > > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > > + &crtc_state->base, > > + DRM_PLANE_HELPER_NO_S > > CALING, > > + DRM_PLANE_HELPER_NO_S > > CALING, > > + true, true); > > + if (ret) > > + return ret; > > + > > + if (!plane_state->base.visible) > > + return 0; > > + > > + ret = intel_plane_check_src_coordinates(plane_state); > > + if (ret) > > + return ret; > > Looks like it is missing a g4x_sprite_check_scaling() call for VLV/CHV. Not needed since VLV/CHV sprites can't scale. > > > Other than the 2 comments above: > > Reviewed-by: José Roberto de Souza <jose.souza@intel.com> > > > + > > + ret = i9xx_check_plane_surface(plane_state); > > + if (ret) > > + return ret; > > + > > + plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state); > > > > - state->ctl = g4x_sprite_ctl(crtc_state, state); > > + return 0; > > +} > > + > > +int skl_plane_check(struct intel_crtc_state *crtc_state, > > + struct intel_plane_state *plane_state) > > +{ > > + struct intel_plane *plane = to_intel_plane(plane_state- > > >base.plane); > > + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > > + int max_scale, min_scale; > > + int ret; > > + > > + /* use scaler when colorkey is not required */ > > + if (!plane_state->ckey.flags) { > > + const struct drm_framebuffer *fb = plane_state- > > >base.fb; > > + > > + min_scale = 1; > > + max_scale = skl_max_scale(crtc_state, > > + fb ? fb->format->format : 0); > > + } else { > > + min_scale = DRM_PLANE_HELPER_NO_SCALING; > > + max_scale = DRM_PLANE_HELPER_NO_SCALING; > > } > > > > + ret = drm_atomic_helper_check_plane_state(&plane_state->base, > > + &crtc_state->base, > > + min_scale, max_scale, > > + true, true); > > + if (ret) > > + return ret; > > + > > + if (!plane_state->base.visible) > > + return 0; > > + > > + ret = intel_plane_check_src_coordinates(plane_state); > > + if (ret) > > + return ret; > > + > > + ret = skl_check_plane_surface(crtc_state, plane_state); > > + if (ret) > > + return ret; > > + > > + plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); > > + > > if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) > > - state->color_ctl = glk_plane_color_ctl(crtc_state, > > state); > > + plane_state->color_ctl = > > glk_plane_color_ctl(crtc_state, > > + plane_stat > > e); > > > > return 0; > > } > > @@ -1559,6 +1635,7 @@ intel_sprite_plane_create(struct > > drm_i915_private *dev_priv, > > intel_plane->update_plane = skl_update_plane; > > intel_plane->disable_plane = skl_disable_plane; > > intel_plane->get_hw_state = skl_plane_get_hw_state; > > + intel_plane->check_plane = skl_plane_check; > > > > if (skl_plane_has_planar(dev_priv, pipe, > > PLANE_SPRITE0 + plane)) { > > @@ -1580,6 +1657,7 @@ intel_sprite_plane_create(struct > > drm_i915_private *dev_priv, > > intel_plane->update_plane = vlv_update_plane; > > intel_plane->disable_plane = vlv_disable_plane; > > intel_plane->get_hw_state = vlv_plane_get_hw_state; > > + intel_plane->check_plane = vlv_sprite_check; > > > > plane_formats = vlv_plane_formats; > > num_plane_formats = ARRAY_SIZE(vlv_plane_formats); > > @@ -1591,6 +1669,7 @@ intel_sprite_plane_create(struct > > drm_i915_private *dev_priv, > > intel_plane->update_plane = ivb_update_plane; > > intel_plane->disable_plane = ivb_disable_plane; > > intel_plane->get_hw_state = ivb_plane_get_hw_state; > > + intel_plane->check_plane = g4x_sprite_check; > > > > plane_formats = snb_plane_formats; > > num_plane_formats = ARRAY_SIZE(snb_plane_formats); > > @@ -1602,6 +1681,7 @@ intel_sprite_plane_create(struct > > drm_i915_private *dev_priv, > > intel_plane->update_plane = g4x_update_plane; > > intel_plane->disable_plane = g4x_disable_plane; > > intel_plane->get_hw_state = g4x_plane_get_hw_state; > > + intel_plane->check_plane = g4x_sprite_check; > > > > modifiers = i9xx_plane_format_modifiers; > > if (IS_GEN6(dev_priv)) { > > @@ -1634,7 +1714,6 @@ intel_sprite_plane_create(struct > > drm_i915_private *dev_priv, > > intel_plane->i9xx_plane = plane; > > intel_plane->id = PLANE_SPRITE0 + plane; > > intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, > > intel_plane->id); > > - intel_plane->check_plane = intel_check_sprite_plane; > > > > possible_crtcs = (1 << pipe); > >
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index dcba645cabb8..eddcdd6e4b3b 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -159,7 +159,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ } intel_state->base.visible = false; - ret = intel_plane->check_plane(intel_plane, crtc_state, intel_state); + ret = intel_plane->check_plane(crtc_state, intel_state); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fdc5bedc5135..9b9eaeda15dd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3350,6 +3350,36 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) return 0; } +static int +i9xx_plane_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + int ret; + + ret = drm_atomic_helper_check_plane_state(&plane_state->base, + &crtc_state->base, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); + if (ret) + return ret; + + if (!plane_state->base.visible) + return 0; + + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; + + ret = i9xx_check_plane_surface(plane_state); + if (ret) + return ret; + + plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); + + return 0; +} + static void i9xx_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) @@ -9680,6 +9710,11 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, u32 offset; int ret; + if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { + DRM_DEBUG_KMS("cursor cannot be tiled\n"); + return -EINVAL; + } + ret = drm_atomic_helper_check_plane_state(&plane_state->base, &crtc_state->base, DRM_PLANE_HELPER_NO_SCALING, @@ -9688,13 +9723,12 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, if (ret) return ret; - if (!fb) + if (!plane_state->base.visible) return 0; - if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { - DRM_DEBUG_KMS("cursor cannot be tiled\n"); - return -EINVAL; - } + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); @@ -9744,8 +9778,7 @@ static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state) return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64); } -static int i845_check_cursor(struct intel_plane *plane, - struct intel_crtc_state *crtc_state, +static int i845_check_cursor(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->base.fb; @@ -9943,10 +9976,10 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state) return true; } -static int i9xx_check_cursor(struct intel_plane *plane, - struct intel_crtc_state *crtc_state, +static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { + struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->base.fb; enum pipe pipe = plane->pipe; @@ -13193,19 +13226,17 @@ intel_cleanup_plane_fb(struct drm_plane *plane, } int -skl_max_scale(struct intel_crtc *intel_crtc, - struct intel_crtc_state *crtc_state, - uint32_t pixel_format) +skl_max_scale(const struct intel_crtc_state *crtc_state, + u32 pixel_format) { - struct drm_i915_private *dev_priv; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); int max_scale, mult; int crtc_clock, max_dotclk, tmpclk1, tmpclk2; - if (!intel_crtc || !crtc_state->base.enable) + if (!crtc_state->base.enable) return DRM_PLANE_HELPER_NO_SCALING; - dev_priv = to_i915(intel_crtc->base.dev); - crtc_clock = crtc_state->base.adjusted_mode.crtc_clock; max_dotclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk; @@ -13229,61 +13260,6 @@ skl_max_scale(struct intel_crtc *intel_crtc, return max_scale; } -static int -intel_check_primary_plane(struct intel_plane *plane, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - struct drm_crtc *crtc = state->base.crtc; - int min_scale = DRM_PLANE_HELPER_NO_SCALING; - int max_scale = DRM_PLANE_HELPER_NO_SCALING; - bool can_position = false; - int ret; - uint32_t pixel_format = 0; - - if (INTEL_GEN(dev_priv) >= 9) { - /* use scaler when colorkey is not required */ - if (!state->ckey.flags) { - min_scale = 1; - if (state->base.fb) - pixel_format = state->base.fb->format->format; - max_scale = skl_max_scale(to_intel_crtc(crtc), - crtc_state, pixel_format); - } - can_position = true; - } - - ret = drm_atomic_helper_check_plane_state(&state->base, - &crtc_state->base, - min_scale, max_scale, - can_position, true); - if (ret) - return ret; - - if (!state->base.fb) - return 0; - - if (INTEL_GEN(dev_priv) >= 9) { - ret = skl_check_plane_surface(crtc_state, state); - if (ret) - return ret; - - state->ctl = skl_plane_ctl(crtc_state, state); - } else { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; - - state->ctl = i9xx_plane_ctl(crtc_state, state); - } - - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) - state->color_ctl = glk_plane_color_ctl(crtc_state, state); - - return 0; -} - static void intel_begin_crtc_commit(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { @@ -13736,8 +13712,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) fbc->possible_framebuffer_bits |= primary->frontbuffer_bit; } - primary->check_plane = intel_check_primary_plane; - if (INTEL_GEN(dev_priv) >= 9) { primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY); @@ -13759,6 +13733,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = skl_update_plane; primary->disable_plane = skl_disable_plane; primary->get_hw_state = skl_plane_get_hw_state; + primary->check_plane = skl_plane_check; plane_funcs = &skl_plane_funcs; } else if (INTEL_GEN(dev_priv) >= 4) { @@ -13770,6 +13745,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = i9xx_update_plane; primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; + primary->check_plane = i9xx_plane_check; plane_funcs = &i965_plane_funcs; } else { @@ -13781,6 +13757,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = i9xx_update_plane; primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; + primary->check_plane = i9xx_plane_check; plane_funcs = &i8xx_plane_funcs; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c6c782e14897..6d57c6a508d4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -973,9 +973,8 @@ struct intel_plane { void (*disable_plane)(struct intel_plane *plane, struct intel_crtc *crtc); bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe); - int (*check_plane)(struct intel_plane *plane, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *state); + int (*check_plane)(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state); }; struct intel_watermark_params { @@ -1637,8 +1636,8 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, u16 skl_scaler_calc_phase(int sub, bool chroma_center); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); -int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, - uint32_t pixel_format); +int skl_max_scale(const struct intel_crtc_state *crtc_state, + u32 pixel_format); static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) { @@ -2112,7 +2111,9 @@ bool skl_plane_has_planar(struct drm_i915_private *dev_priv, unsigned int skl_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); - +int skl_plane_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state); +int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); /* intel_tv.c */ void intel_tv_init(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 0d3931b8a981..36e150885897 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -228,6 +228,39 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) #endif } +int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) +{ + const struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_rect *src = &plane_state->base.src; + u32 src_x, src_y, src_w, src_h; + + /* + * Hardware doesn't handle subpixel coordinates. + * Adjust to (macro)pixel boundary, but be careful not to + * increase the source viewport size, because that could + * push the downscaling factor out of bounds. + */ + src_x = src->x1 >> 16; + src_w = drm_rect_width(src) >> 16; + src_y = src->y1 >> 16; + src_h = drm_rect_height(src) >> 16; + + src->x1 = src_x << 16; + src->x2 = (src_x + src_w) << 16; + src->y1 = src_y << 16; + src->y2 = (src_y + src_h) << 16; + + if (fb->format->is_yuv && + fb->format->format != DRM_FORMAT_NV12 && + (src_x & 1 || src_w & 1)) { + DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", + src_x, src_w); + return -EINVAL; + } + + return 0; +} + unsigned int skl_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, @@ -983,146 +1016,189 @@ g4x_plane_get_hw_state(struct intel_plane *plane, } static int -intel_check_sprite_plane(struct intel_plane *plane, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *state) +g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - struct drm_framebuffer *fb = state->base.fb; - int max_scale, min_scale; - int ret; - uint32_t pixel_format = 0; - - if (!fb) { - state->base.visible = false; + const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_rect *src = &plane_state->base.src; + const struct drm_rect *dst = &plane_state->base.dst; + int src_x, src_y, src_w, src_h, crtc_w, crtc_h; + const struct drm_display_mode *adjusted_mode = + &crtc_state->base.adjusted_mode; + unsigned int cpp = fb->format->cpp[0]; + unsigned int width_bytes; + int min_width, min_height; + + crtc_w = drm_rect_width(dst); + crtc_h = drm_rect_height(dst); + + src_x = src->x1 >> 16; + src_y = src->y1 >> 16; + src_w = drm_rect_width(src) >> 16; + src_h = drm_rect_height(src) >> 16; + + if (src_w == crtc_w && src_h == crtc_h) return 0; + + min_width = 3; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + if (src_h & 1) { + DRM_DEBUG_KMS("Source height must be even with interlaced modes\n"); + return -EINVAL; + } + min_height = 6; + } else { + min_height = 3; } - /* Don't modify another pipe's plane */ - if (plane->pipe != crtc->pipe) { - DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); + width_bytes = ((src_x * cpp) & 63) + src_w * cpp; + + if (src_w < min_width || src_h < min_height || + src_w > 2048 || src_h > 2048) { + DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n", + src_w, src_h, min_width, min_height, 2048, 2048); return -EINVAL; } - /* FIXME check all gen limits */ - if (fb->width < 3 || fb->height < 3 || - fb->pitches[0] > plane->max_stride(plane, fb->format->format, - fb->modifier, DRM_MODE_ROTATE_0)) { - DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); + if (width_bytes > 4096) { + DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n", + width_bytes, 4096); return -EINVAL; } - if (INTEL_GEN(dev_priv) >= 9) { - if (state->base.fb) - pixel_format = state->base.fb->format->format; - /* use scaler when colorkey is not required */ - if (!state->ckey.flags) { - min_scale = 1; - max_scale = - skl_max_scale(crtc, crtc_state, pixel_format); - } else { - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; - } + if (width_bytes > 4096 || fb->pitches[0] > 4096) { + DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n", + fb->pitches[0], 4096); + return -EINVAL; + } + + return 0; +} + +static int +g4x_sprite_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + int max_scale, min_scale; + int ret; + + if (INTEL_GEN(dev_priv) < 7) { + min_scale = 1; + max_scale = 16 << 16; + } else if (IS_IVYBRIDGE(dev_priv)) { + min_scale = 1; + max_scale = 2 << 16; } else { - if (INTEL_GEN(dev_priv) < 7) { - min_scale = 1; - max_scale = 16 << 16; - } else if (IS_IVYBRIDGE(dev_priv)) { - min_scale = 1; - max_scale = 2 << 16; - } else { - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; - } + min_scale = DRM_PLANE_HELPER_NO_SCALING; + max_scale = DRM_PLANE_HELPER_NO_SCALING; } - ret = drm_atomic_helper_check_plane_state(&state->base, + ret = drm_atomic_helper_check_plane_state(&plane_state->base, &crtc_state->base, min_scale, max_scale, true, true); if (ret) return ret; - if (state->base.visible) { - struct drm_rect *src = &state->base.src; - struct drm_rect *dst = &state->base.dst; - unsigned int crtc_w = drm_rect_width(dst); - unsigned int crtc_h = drm_rect_height(dst); - uint32_t src_x, src_y, src_w, src_h; + if (!plane_state->base.visible) + return 0; - /* - * Hardware doesn't handle subpixel coordinates. - * Adjust to (macro)pixel boundary, but be careful not to - * increase the source viewport size, because that could - * push the downscaling factor out of bounds. - */ - src_x = src->x1 >> 16; - src_w = drm_rect_width(src) >> 16; - src_y = src->y1 >> 16; - src_h = drm_rect_height(src) >> 16; - - src->x1 = src_x << 16; - src->x2 = (src_x + src_w) << 16; - src->y1 = src_y << 16; - src->y2 = (src_y + src_h) << 16; - - if (fb->format->is_yuv && - fb->format->format != DRM_FORMAT_NV12 && - (src_x % 2 || src_w % 2)) { - DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", - src_x, src_w); - return -EINVAL; - } + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; - /* Check size restrictions when scaling */ - if (src_w != crtc_w || src_h != crtc_h) { - unsigned int width_bytes; - int cpp = fb->format->cpp[0]; - - width_bytes = ((src_x * cpp) & 63) + src_w * cpp; - - /* FIXME interlacing min height is 6 */ - if (INTEL_GEN(dev_priv) < 9 && ( - src_w < 3 || src_h < 3 || - src_w > 2048 || src_h > 2048 || - crtc_w < 3 || crtc_h < 3 || - width_bytes > 4096 || fb->pitches[0] > 4096)) { - DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); - return -EINVAL; - } - } - } + ret = g4x_sprite_check_scaling(crtc_state, plane_state); + if (ret) + return ret; - if (INTEL_GEN(dev_priv) >= 9) { - ret = skl_check_plane_surface(crtc_state, state); - if (ret) - return ret; + ret = i9xx_check_plane_surface(plane_state); + if (ret) + return ret; - state->ctl = skl_plane_ctl(crtc_state, state); - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; + if (INTEL_GEN(dev_priv) >= 7) + plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state); + else + plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state); - state->ctl = vlv_sprite_ctl(crtc_state, state); - } else if (INTEL_GEN(dev_priv) >= 7) { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; + return 0; +} - state->ctl = ivb_sprite_ctl(crtc_state, state); - } else { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; +static int +vlv_sprite_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + int ret; + + ret = drm_atomic_helper_check_plane_state(&plane_state->base, + &crtc_state->base, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); + if (ret) + return ret; + + if (!plane_state->base.visible) + return 0; + + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; + + ret = i9xx_check_plane_surface(plane_state); + if (ret) + return ret; + + plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state); - state->ctl = g4x_sprite_ctl(crtc_state, state); + return 0; +} + +int skl_plane_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + int max_scale, min_scale; + int ret; + + /* use scaler when colorkey is not required */ + if (!plane_state->ckey.flags) { + const struct drm_framebuffer *fb = plane_state->base.fb; + + min_scale = 1; + max_scale = skl_max_scale(crtc_state, + fb ? fb->format->format : 0); + } else { + min_scale = DRM_PLANE_HELPER_NO_SCALING; + max_scale = DRM_PLANE_HELPER_NO_SCALING; } + ret = drm_atomic_helper_check_plane_state(&plane_state->base, + &crtc_state->base, + min_scale, max_scale, + true, true); + if (ret) + return ret; + + if (!plane_state->base.visible) + return 0; + + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; + + ret = skl_check_plane_surface(crtc_state, plane_state); + if (ret) + return ret; + + plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) - state->color_ctl = glk_plane_color_ctl(crtc_state, state); + plane_state->color_ctl = glk_plane_color_ctl(crtc_state, + plane_state); return 0; } @@ -1559,6 +1635,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = skl_update_plane; intel_plane->disable_plane = skl_disable_plane; intel_plane->get_hw_state = skl_plane_get_hw_state; + intel_plane->check_plane = skl_plane_check; if (skl_plane_has_planar(dev_priv, pipe, PLANE_SPRITE0 + plane)) { @@ -1580,6 +1657,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; intel_plane->get_hw_state = vlv_plane_get_hw_state; + intel_plane->check_plane = vlv_sprite_check; plane_formats = vlv_plane_formats; num_plane_formats = ARRAY_SIZE(vlv_plane_formats); @@ -1591,6 +1669,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = ivb_update_plane; intel_plane->disable_plane = ivb_disable_plane; intel_plane->get_hw_state = ivb_plane_get_hw_state; + intel_plane->check_plane = g4x_sprite_check; plane_formats = snb_plane_formats; num_plane_formats = ARRAY_SIZE(snb_plane_formats); @@ -1602,6 +1681,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = g4x_update_plane; intel_plane->disable_plane = g4x_disable_plane; intel_plane->get_hw_state = g4x_plane_get_hw_state; + intel_plane->check_plane = g4x_sprite_check; modifiers = i9xx_plane_format_modifiers; if (IS_GEN6(dev_priv)) { @@ -1634,7 +1714,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->i9xx_plane = plane; intel_plane->id = PLANE_SPRITE0 + plane; intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id); - intel_plane->check_plane = intel_check_sprite_plane; possible_crtcs = (1 << pipe);