Message ID | 55DEE19E.9070702@mblankhorst.nl (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Aug 27, 2015 at 12:08:30PM +0200, Maarten Lankhorst wrote: > This appears to make all the cursor tests really slow because of the many calls to skl_update_wm > when the cursor plane visibility is changed. It performs does 3 vblanks each time it's called, and > it's probably called more than once on each update. On all other platforms wm updates (right now at least) don't do any vblank waits, which means changing cursors actually _does_ cause tons of underruns. Can we perhaps add a hack in skl to do the same (maybe just for cursors) so that we can get this in? There's lots other work that really wants proper universal planes ... -Daniel > > Smarter watermark updates will hopefully fix this.. > > This patch is tested with Xorg and kms_cursor_crc, and is just a RFC. :) > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> > --- > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 05523491ad6f..bf5f814f72ae 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -263,11 +263,11 @@ struct i915_hotplug { > for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) > #define for_each_plane(__dev_priv, __pipe, __p) \ > for ((__p) = 0; \ > - (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \ > + (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1 + IS_GEN9(__dev_priv); \ > (__p)++) > #define for_each_sprite(__dev_priv, __p, __s) \ > for ((__s) = 0; \ > - (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)]; \ > + (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)] + IS_GEN9(__dev_priv); \ > (__s)++) > > #define for_each_crtc(dev, crtc) \ > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 92e3f074ae30..307d1374daa5 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -1402,7 +1402,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, > > if (INTEL_INFO(dev)->gen >= 9) { > for_each_sprite(dev_priv, pipe, sprite) { > - val = I915_READ(PLANE_CTL(pipe, sprite)); > + val = I915_READ(PLANE_CTL(pipe, sprite + 1)); > I915_STATE_WARN(val & PLANE_CTL_ENABLE, > "plane %d assertion failure, should be off on pipe %c but is still active\n", > sprite, pipe_name(pipe)); > @@ -11563,12 +11563,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, > bool mode_changed = needs_modeset(crtc_state); > bool was_crtc_enabled = crtc->state->active; > bool is_crtc_enabled = crtc_state->active; > - > + enum drm_plane_type plane_type = plane->type; > bool turn_off, turn_on, visible, was_visible; > struct drm_framebuffer *fb = plane_state->fb; > > + if (IS_GEN9(dev) && plane->type == DRM_PLANE_TYPE_CURSOR) > + plane_type = DRM_PLANE_TYPE_OVERLAY; > + > if (crtc_state && INTEL_INFO(dev)->gen >= 9 && > - plane->type != DRM_PLANE_TYPE_CURSOR) { > + plane_type != DRM_PLANE_TYPE_CURSOR) { > ret = skl_update_scaler_plane( > to_intel_crtc_state(crtc_state), > to_intel_plane_state(plane_state)); > @@ -11601,7 +11604,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, > if (turn_on) { > intel_crtc->atomic.update_wm_pre = true; > /* must disable cxsr around plane enable/disable */ > - if (plane->type != DRM_PLANE_TYPE_CURSOR) { > + if (plane_type != DRM_PLANE_TYPE_CURSOR) { > intel_crtc->atomic.disable_cxsr = true; > /* to potentially re-enable cxsr */ > intel_crtc->atomic.wait_vblank = true; > @@ -11610,7 +11613,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, > } else if (turn_off) { > intel_crtc->atomic.update_wm_post = true; > /* must disable cxsr around plane enable/disable */ > - if (plane->type != DRM_PLANE_TYPE_CURSOR) { > + if (plane_type != DRM_PLANE_TYPE_CURSOR) { > if (is_crtc_enabled) > intel_crtc->atomic.wait_vblank = true; > intel_crtc->atomic.disable_cxsr = true; > @@ -11623,7 +11626,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, > intel_crtc->atomic.fb_bits |= > to_intel_plane(plane)->frontbuffer_bit; > > - switch (plane->type) { > + switch (plane_type) { > case DRM_PLANE_TYPE_PRIMARY: > intel_crtc->atomic.wait_for_flips = true; > intel_crtc->atomic.pre_disable_primary = turn_off; > @@ -13770,7 +13773,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) > struct intel_crtc_state *crtc_state = NULL; > struct drm_plane *primary = NULL; > struct drm_plane *cursor = NULL; > - int i, ret; > + int i, ret, sprite; > > intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); > if (intel_crtc == NULL) > @@ -13797,9 +13800,31 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) > if (!primary) > goto fail; > > - cursor = intel_cursor_plane_create(dev, pipe); > - if (!cursor) > - goto fail; > + if (!IS_GEN9(dev)) { > + cursor = intel_cursor_plane_create(dev, pipe); > + if (!cursor) > + goto fail; > + } > + > + for_each_sprite(dev_priv, pipe, sprite) { > + enum drm_plane_type plane_type; > + struct drm_plane *plane; > + > + if (sprite < INTEL_INFO(dev_priv)->num_sprites[pipe]) > + plane_type = DRM_PLANE_TYPE_OVERLAY; > + else > + plane_type = DRM_PLANE_TYPE_CURSOR; > + > + plane = intel_plane_init(dev, pipe, sprite, plane_type); > + if (IS_ERR(plane)) { > + DRM_DEBUG_KMS("pipe %c sprite %c init failed: %ld\n", > + pipe_name(pipe), sprite_name(pipe, sprite), PTR_ERR(plane)); > + goto fail; > + } > + > + if (plane_type == DRM_PLANE_TYPE_CURSOR) > + cursor = plane; > + } > > ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary, > cursor, &intel_crtc_funcs); > @@ -14724,7 +14749,6 @@ void intel_modeset_init_hw(struct drm_device *dev) > void intel_modeset_init(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = dev->dev_private; > - int sprite, ret; > enum pipe pipe; > struct intel_crtc *crtc; > > @@ -14778,15 +14802,8 @@ void intel_modeset_init(struct drm_device *dev) > INTEL_INFO(dev)->num_pipes, > INTEL_INFO(dev)->num_pipes > 1 ? "s" : ""); > > - for_each_pipe(dev_priv, pipe) { > + for_each_pipe(dev_priv, pipe) > intel_crtc_init(dev, pipe); > - for_each_sprite(dev_priv, pipe, sprite) { > - ret = intel_plane_init(dev, pipe, sprite); > - if (ret) > - DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n", > - pipe_name(pipe), sprite_name(pipe, sprite), ret); > - } > - } > > intel_init_dpio(dev); > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 3908059fc42f..df3bca6e4031 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -890,11 +890,12 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) > > /* > * Returns the number of planes for this pipe, ie the number of sprites + 1 > - * (primary plane). This doesn't count the cursor plane then. > + * (primary plane). This doesn't count the cursor plane except on GEN9, > + * which has a universal plane masked as cursor plane. > */ > static inline unsigned int intel_num_planes(struct intel_crtc *crtc) > { > - return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1; > + return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1 + IS_GEN9(crtc->base.dev); > } > > /* intel_fifo_underrun.c */ > @@ -1388,7 +1389,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); > > > /* intel_sprite.c */ > -int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); > +struct drm_plane *intel_plane_init(struct drm_device *dev, enum pipe pipe, > + int plane, enum drm_plane_type plane_type); > int intel_sprite_set_colorkey(struct drm_device *dev, void *data, > struct drm_file *file_priv); > void intel_pipe_update_start(struct intel_crtc *crtc, > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c > index fff0c22682ee..b6ea345e2f1b 100644 > --- a/drivers/gpu/drm/i915/intel_pm.c > +++ b/drivers/gpu/drm/i915/intel_pm.c > @@ -2970,7 +2970,7 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, > struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > enum pipe pipe = intel_crtc->pipe; > struct skl_ddb_entry *alloc = &ddb->pipe[pipe]; > - uint16_t alloc_size, start, cursor_blocks; > + uint16_t alloc_size, start; > uint16_t minimum[I915_MAX_PLANES]; > uint16_t y_minimum[I915_MAX_PLANES]; > unsigned int total_data_rate; > @@ -2984,12 +2984,16 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, > return; > } > > - cursor_blocks = skl_cursor_allocation(config); > - ddb->cursor[pipe].start = alloc->end - cursor_blocks; > - ddb->cursor[pipe].end = alloc->end; > + if (!IS_GEN9(dev)) { > + uint16_t cursor_blocks; > > - alloc_size -= cursor_blocks; > - alloc->end -= cursor_blocks; > + cursor_blocks = skl_cursor_allocation(config); > + ddb->cursor[pipe].start = alloc->end - cursor_blocks; > + ddb->cursor[pipe].end = alloc->end; > + > + alloc_size -= cursor_blocks; > + alloc->end -= cursor_blocks; > + } > > /* 1. Allocate the mininum required blocks for each active plane */ > for_each_plane(dev_priv, pipe, plane) { > @@ -3186,7 +3190,7 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, > > fb = crtc->cursor->state->fb; > p->cursor.y_bytes_per_pixel = 0; > - if (fb) { > + if (!IS_GEN9(dev) && fb) { > p->cursor.enabled = true; > p->cursor.bytes_per_pixel = fb->bits_per_pixel / 8; > p->cursor.horiz_pixels = crtc->cursor->state->crtc_w; > @@ -3202,8 +3206,11 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, > list_for_each_entry(plane, &dev->mode_config.plane_list, head) { > struct intel_plane *intel_plane = to_intel_plane(plane); > > - if (intel_plane->pipe == pipe && > - plane->type == DRM_PLANE_TYPE_OVERLAY) > + if (intel_plane->pipe != pipe) > + continue; > + > + if (plane->type == DRM_PLANE_TYPE_OVERLAY || > + (IS_GEN9(dev) && plane->type == DRM_PLANE_TYPE_CURSOR)) > p->plane[i++] = intel_plane->wm; > } > } > @@ -3390,11 +3397,13 @@ static void skl_compute_wm_results(struct drm_device *dev, > > temp = 0; > > - temp |= p_wm->wm[level].cursor_res_l << PLANE_WM_LINES_SHIFT; > - temp |= p_wm->wm[level].cursor_res_b; > + if (!IS_GEN9(dev)) { > + temp |= p_wm->wm[level].cursor_res_l << PLANE_WM_LINES_SHIFT; > + temp |= p_wm->wm[level].cursor_res_b; > > - if (p_wm->wm[level].cursor_en) > - temp |= PLANE_WM_EN; > + if (p_wm->wm[level].cursor_en) > + temp |= PLANE_WM_EN; > + } > > r->cursor[pipe][level] = temp; > > @@ -3412,10 +3421,12 @@ static void skl_compute_wm_results(struct drm_device *dev, > } > > temp = 0; > - temp |= p_wm->trans_wm.cursor_res_l << PLANE_WM_LINES_SHIFT; > - temp |= p_wm->trans_wm.cursor_res_b; > - if (p_wm->trans_wm.cursor_en) > - temp |= PLANE_WM_EN; > + if (!IS_GEN9(dev)) { > + temp |= p_wm->trans_wm.cursor_res_l << PLANE_WM_LINES_SHIFT; > + temp |= p_wm->trans_wm.cursor_res_b; > + if (p_wm->trans_wm.cursor_en) > + temp |= PLANE_WM_EN; > + } > > r->cursor_trans[pipe] = temp; > > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c > index 9d8af2f8a875..596fa4319681 100644 > --- a/drivers/gpu/drm/i915/intel_sprite.c > +++ b/drivers/gpu/drm/i915/intel_sprite.c > @@ -961,7 +961,8 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, > return -EINVAL; > > plane = drm_plane_find(dev, set->plane_id); > - if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY) > + if (!plane || plane->type == DRM_PLANE_TYPE_PRIMARY || > + (!IS_GEN9(dev) && plane->type == DRM_PLANE_TYPE_CURSOR)) > return -ENOENT; > > drm_modeset_acquire_init(&ctx, 0); > @@ -1040,8 +1041,8 @@ static uint32_t skl_plane_formats[] = { > DRM_FORMAT_VYUY, > }; > > -int > -intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) > +struct drm_plane * > +intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane, enum drm_plane_type plane_type) > { > struct intel_plane *intel_plane; > struct intel_plane_state *state; > @@ -1051,16 +1052,16 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) > int ret; > > if (INTEL_INFO(dev)->gen < 5) > - return -ENODEV; > + return ERR_PTR(-ENODEV); > > intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); > if (!intel_plane) > - return -ENOMEM; > + return ERR_PTR(-ENOMEM); > > state = intel_create_plane_state(&intel_plane->base); > if (!state) { > kfree(intel_plane); > - return -ENOMEM; > + return ERR_PTR(-ENOMEM); > } > intel_plane->base.state = &state->base; > > @@ -1116,7 +1117,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) > break; > default: > kfree(intel_plane); > - return -ENODEV; > + return ERR_PTR(-ENODEV); > } > > intel_plane->pipe = pipe; > @@ -1128,7 +1129,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) > ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, > &intel_plane_funcs, > plane_formats, num_plane_formats, > - DRM_PLANE_TYPE_OVERLAY); > + plane_type); > if (ret) { > kfree(intel_plane); > goto out; > @@ -1138,6 +1139,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) > > drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); > > + return &intel_plane->base; > + > out: > - return ret; > + return ERR_PTR(ret); > } > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Op 02-09-15 om 11:15 schreef Daniel Vetter: > On Thu, Aug 27, 2015 at 12:08:30PM +0200, Maarten Lankhorst wrote: >> This appears to make all the cursor tests really slow because of the many calls to skl_update_wm >> when the cursor plane visibility is changed. It performs does 3 vblanks each time it's called, and >> it's probably called more than once on each update. > On all other platforms wm updates (right now at least) don't do any vblank > waits, which means changing cursors actually _does_ cause tons of > underruns. Can we perhaps add a hack in skl to do the same (maybe just for > cursors) so that we can get this in? There's lots other work that really > wants proper universal planes ... > Well this is easily fixed by moving it to unpin_work, so it runs after the next vblank interrupt. If that patch series is too far out annotate wm changed, kill all intel_wait_vblank calls inside post_plane_update and run that function after drm_atomic_helper_wait_for_vblanks. ~Maarten
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 05523491ad6f..bf5f814f72ae 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -263,11 +263,11 @@ struct i915_hotplug { for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) #define for_each_plane(__dev_priv, __pipe, __p) \ for ((__p) = 0; \ - (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \ + (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1 + IS_GEN9(__dev_priv); \ (__p)++) #define for_each_sprite(__dev_priv, __p, __s) \ for ((__s) = 0; \ - (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)]; \ + (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)] + IS_GEN9(__dev_priv); \ (__s)++) #define for_each_crtc(dev, crtc) \ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 92e3f074ae30..307d1374daa5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1402,7 +1402,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, if (INTEL_INFO(dev)->gen >= 9) { for_each_sprite(dev_priv, pipe, sprite) { - val = I915_READ(PLANE_CTL(pipe, sprite)); + val = I915_READ(PLANE_CTL(pipe, sprite + 1)); I915_STATE_WARN(val & PLANE_CTL_ENABLE, "plane %d assertion failure, should be off on pipe %c but is still active\n", sprite, pipe_name(pipe)); @@ -11563,12 +11563,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, bool mode_changed = needs_modeset(crtc_state); bool was_crtc_enabled = crtc->state->active; bool is_crtc_enabled = crtc_state->active; - + enum drm_plane_type plane_type = plane->type; bool turn_off, turn_on, visible, was_visible; struct drm_framebuffer *fb = plane_state->fb; + if (IS_GEN9(dev) && plane->type == DRM_PLANE_TYPE_CURSOR) + plane_type = DRM_PLANE_TYPE_OVERLAY; + if (crtc_state && INTEL_INFO(dev)->gen >= 9 && - plane->type != DRM_PLANE_TYPE_CURSOR) { + plane_type != DRM_PLANE_TYPE_CURSOR) { ret = skl_update_scaler_plane( to_intel_crtc_state(crtc_state), to_intel_plane_state(plane_state)); @@ -11601,7 +11604,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, if (turn_on) { intel_crtc->atomic.update_wm_pre = true; /* must disable cxsr around plane enable/disable */ - if (plane->type != DRM_PLANE_TYPE_CURSOR) { + if (plane_type != DRM_PLANE_TYPE_CURSOR) { intel_crtc->atomic.disable_cxsr = true; /* to potentially re-enable cxsr */ intel_crtc->atomic.wait_vblank = true; @@ -11610,7 +11613,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, } else if (turn_off) { intel_crtc->atomic.update_wm_post = true; /* must disable cxsr around plane enable/disable */ - if (plane->type != DRM_PLANE_TYPE_CURSOR) { + if (plane_type != DRM_PLANE_TYPE_CURSOR) { if (is_crtc_enabled) intel_crtc->atomic.wait_vblank = true; intel_crtc->atomic.disable_cxsr = true; @@ -11623,7 +11626,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, intel_crtc->atomic.fb_bits |= to_intel_plane(plane)->frontbuffer_bit; - switch (plane->type) { + switch (plane_type) { case DRM_PLANE_TYPE_PRIMARY: intel_crtc->atomic.wait_for_flips = true; intel_crtc->atomic.pre_disable_primary = turn_off; @@ -13770,7 +13773,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) struct intel_crtc_state *crtc_state = NULL; struct drm_plane *primary = NULL; struct drm_plane *cursor = NULL; - int i, ret; + int i, ret, sprite; intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) @@ -13797,9 +13800,31 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) if (!primary) goto fail; - cursor = intel_cursor_plane_create(dev, pipe); - if (!cursor) - goto fail; + if (!IS_GEN9(dev)) { + cursor = intel_cursor_plane_create(dev, pipe); + if (!cursor) + goto fail; + } + + for_each_sprite(dev_priv, pipe, sprite) { + enum drm_plane_type plane_type; + struct drm_plane *plane; + + if (sprite < INTEL_INFO(dev_priv)->num_sprites[pipe]) + plane_type = DRM_PLANE_TYPE_OVERLAY; + else + plane_type = DRM_PLANE_TYPE_CURSOR; + + plane = intel_plane_init(dev, pipe, sprite, plane_type); + if (IS_ERR(plane)) { + DRM_DEBUG_KMS("pipe %c sprite %c init failed: %ld\n", + pipe_name(pipe), sprite_name(pipe, sprite), PTR_ERR(plane)); + goto fail; + } + + if (plane_type == DRM_PLANE_TYPE_CURSOR) + cursor = plane; + } ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary, cursor, &intel_crtc_funcs); @@ -14724,7 +14749,6 @@ void intel_modeset_init_hw(struct drm_device *dev) void intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int sprite, ret; enum pipe pipe; struct intel_crtc *crtc; @@ -14778,15 +14802,8 @@ void intel_modeset_init(struct drm_device *dev) INTEL_INFO(dev)->num_pipes, INTEL_INFO(dev)->num_pipes > 1 ? "s" : ""); - for_each_pipe(dev_priv, pipe) { + for_each_pipe(dev_priv, pipe) intel_crtc_init(dev, pipe); - for_each_sprite(dev_priv, pipe, sprite) { - ret = intel_plane_init(dev, pipe, sprite); - if (ret) - DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n", - pipe_name(pipe), sprite_name(pipe, sprite), ret); - } - } intel_init_dpio(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3908059fc42f..df3bca6e4031 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -890,11 +890,12 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) /* * Returns the number of planes for this pipe, ie the number of sprites + 1 - * (primary plane). This doesn't count the cursor plane then. + * (primary plane). This doesn't count the cursor plane except on GEN9, + * which has a universal plane masked as cursor plane. */ static inline unsigned int intel_num_planes(struct intel_crtc *crtc) { - return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1; + return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1 + IS_GEN9(crtc->base.dev); } /* intel_fifo_underrun.c */ @@ -1388,7 +1389,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); /* intel_sprite.c */ -int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); +struct drm_plane *intel_plane_init(struct drm_device *dev, enum pipe pipe, + int plane, enum drm_plane_type plane_type); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); void intel_pipe_update_start(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fff0c22682ee..b6ea345e2f1b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2970,7 +2970,7 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; struct skl_ddb_entry *alloc = &ddb->pipe[pipe]; - uint16_t alloc_size, start, cursor_blocks; + uint16_t alloc_size, start; uint16_t minimum[I915_MAX_PLANES]; uint16_t y_minimum[I915_MAX_PLANES]; unsigned int total_data_rate; @@ -2984,12 +2984,16 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, return; } - cursor_blocks = skl_cursor_allocation(config); - ddb->cursor[pipe].start = alloc->end - cursor_blocks; - ddb->cursor[pipe].end = alloc->end; + if (!IS_GEN9(dev)) { + uint16_t cursor_blocks; - alloc_size -= cursor_blocks; - alloc->end -= cursor_blocks; + cursor_blocks = skl_cursor_allocation(config); + ddb->cursor[pipe].start = alloc->end - cursor_blocks; + ddb->cursor[pipe].end = alloc->end; + + alloc_size -= cursor_blocks; + alloc->end -= cursor_blocks; + } /* 1. Allocate the mininum required blocks for each active plane */ for_each_plane(dev_priv, pipe, plane) { @@ -3186,7 +3190,7 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, fb = crtc->cursor->state->fb; p->cursor.y_bytes_per_pixel = 0; - if (fb) { + if (!IS_GEN9(dev) && fb) { p->cursor.enabled = true; p->cursor.bytes_per_pixel = fb->bits_per_pixel / 8; p->cursor.horiz_pixels = crtc->cursor->state->crtc_w; @@ -3202,8 +3206,11 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, list_for_each_entry(plane, &dev->mode_config.plane_list, head) { struct intel_plane *intel_plane = to_intel_plane(plane); - if (intel_plane->pipe == pipe && - plane->type == DRM_PLANE_TYPE_OVERLAY) + if (intel_plane->pipe != pipe) + continue; + + if (plane->type == DRM_PLANE_TYPE_OVERLAY || + (IS_GEN9(dev) && plane->type == DRM_PLANE_TYPE_CURSOR)) p->plane[i++] = intel_plane->wm; } } @@ -3390,11 +3397,13 @@ static void skl_compute_wm_results(struct drm_device *dev, temp = 0; - temp |= p_wm->wm[level].cursor_res_l << PLANE_WM_LINES_SHIFT; - temp |= p_wm->wm[level].cursor_res_b; + if (!IS_GEN9(dev)) { + temp |= p_wm->wm[level].cursor_res_l << PLANE_WM_LINES_SHIFT; + temp |= p_wm->wm[level].cursor_res_b; - if (p_wm->wm[level].cursor_en) - temp |= PLANE_WM_EN; + if (p_wm->wm[level].cursor_en) + temp |= PLANE_WM_EN; + } r->cursor[pipe][level] = temp; @@ -3412,10 +3421,12 @@ static void skl_compute_wm_results(struct drm_device *dev, } temp = 0; - temp |= p_wm->trans_wm.cursor_res_l << PLANE_WM_LINES_SHIFT; - temp |= p_wm->trans_wm.cursor_res_b; - if (p_wm->trans_wm.cursor_en) - temp |= PLANE_WM_EN; + if (!IS_GEN9(dev)) { + temp |= p_wm->trans_wm.cursor_res_l << PLANE_WM_LINES_SHIFT; + temp |= p_wm->trans_wm.cursor_res_b; + if (p_wm->trans_wm.cursor_en) + temp |= PLANE_WM_EN; + } r->cursor_trans[pipe] = temp; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9d8af2f8a875..596fa4319681 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -961,7 +961,8 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, return -EINVAL; plane = drm_plane_find(dev, set->plane_id); - if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY) + if (!plane || plane->type == DRM_PLANE_TYPE_PRIMARY || + (!IS_GEN9(dev) && plane->type == DRM_PLANE_TYPE_CURSOR)) return -ENOENT; drm_modeset_acquire_init(&ctx, 0); @@ -1040,8 +1041,8 @@ static uint32_t skl_plane_formats[] = { DRM_FORMAT_VYUY, }; -int -intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) +struct drm_plane * +intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane, enum drm_plane_type plane_type) { struct intel_plane *intel_plane; struct intel_plane_state *state; @@ -1051,16 +1052,16 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) int ret; if (INTEL_INFO(dev)->gen < 5) - return -ENODEV; + return ERR_PTR(-ENODEV); intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); if (!intel_plane) - return -ENOMEM; + return ERR_PTR(-ENOMEM); state = intel_create_plane_state(&intel_plane->base); if (!state) { kfree(intel_plane); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } intel_plane->base.state = &state->base; @@ -1116,7 +1117,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) break; default: kfree(intel_plane); - return -ENODEV; + return ERR_PTR(-ENODEV); } intel_plane->pipe = pipe; @@ -1128,7 +1129,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, - DRM_PLANE_TYPE_OVERLAY); + plane_type); if (ret) { kfree(intel_plane); goto out; @@ -1138,6 +1139,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); + return &intel_plane->base; + out: - return ret; + return ERR_PTR(ret); }
This appears to make all the cursor tests really slow because of the many calls to skl_update_wm when the cursor plane visibility is changed. It performs does 3 vblanks each time it's called, and it's probably called more than once on each update. Smarter watermark updates will hopefully fix this.. This patch is tested with Xorg and kms_cursor_crc, and is just a RFC. :) Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> ---