Message ID | 20180921173945.6276-7-maarten.lankhorst@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/i915/gen11: Enable planar format support on gen11. | expand |
On Fri, Sep 21, 2018 at 07:39:44PM +0200, Maarten Lankhorst wrote: > The UV plane is the master plane that does all color correction etc. > It needs to be programmed with the dimensions for color plane 1 (UV). > > The Y plane just feeds the Y pixels to it. Program the scaler from the > master only, and set PLANE_CTL_YUV420_Y_PLANE on the slave plane. > > Changes since v1: > - Make a common skl_program_plane, and use it for both plane updates. > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> > --- > drivers/gpu/drm/i915/i915_reg.h | 1 + > drivers/gpu/drm/i915/intel_sprite.c | 50 +++++++++++++++++++++-------- > 2 files changed, 38 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index b614a06b66c4..a3129a4c15cc 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -6511,6 +6511,7 @@ enum { > #define PLANE_CTL_KEY_ENABLE_DESTINATION (2 << 21) > #define PLANE_CTL_ORDER_BGRX (0 << 20) > #define PLANE_CTL_ORDER_RGBX (1 << 20) > +#define PLANE_CTL_YUV420_Y_PLANE (1 << 19) > #define PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709 (1 << 18) > #define PLANE_CTL_YUV422_ORDER_MASK (0x3 << 16) > #define PLANE_CTL_YUV422_YUYV (0 << 16) > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c > index c4e05b0b60bf..708d2dfd59d7 100644 > --- a/drivers/gpu/drm/i915/intel_sprite.c > +++ b/drivers/gpu/drm/i915/intel_sprite.c > @@ -339,23 +339,23 @@ skl_program_scaler(struct drm_i915_private *dev_priv, > ((crtc_w + 1) << 16)|(crtc_h + 1)); > } > > -void > -skl_update_plane(struct intel_plane *plane, > - const struct intel_crtc_state *crtc_state, > - const struct intel_plane_state *plane_state) > +static void > +skl_program_plane(struct intel_plane *plane, > + const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state *plane_state, > + int color_plane, bool slave, u32 plane_ctl) > { > struct drm_i915_private *dev_priv = to_i915(plane->base.dev); > enum plane_id plane_id = plane->id; > enum pipe pipe = plane->pipe; > - u32 plane_ctl = plane_state->ctl; > const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; > - u32 surf_addr = plane_state->color_plane[0].offset; > - u32 stride = skl_plane_stride(plane_state, 0); > + u32 surf_addr = plane_state->color_plane[color_plane].offset; > + u32 stride = skl_plane_stride(plane_state, color_plane); > u32 aux_stride = skl_plane_stride(plane_state, 1); > int crtc_x = plane_state->base.dst.x1; > int crtc_y = plane_state->base.dst.y1; > - uint32_t x = plane_state->color_plane[0].x; > - uint32_t y = plane_state->color_plane[0].y; > + uint32_t x = plane_state->color_plane[color_plane].x; > + uint32_t y = plane_state->color_plane[color_plane].y; > uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; > uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; > struct intel_plane *linked = plane_state->linked_plane; > @@ -409,7 +409,9 @@ skl_update_plane(struct intel_plane *plane, > > /* program plane scaler */ > if (plane_state->scaler_id >= 0) { > - skl_program_scaler(dev_priv, plane, crtc_state, plane_state); > + if (!slave) > + skl_program_scaler(dev_priv, plane, > + crtc_state, plane_state); > > I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0); > } else { > @@ -424,6 +426,25 @@ skl_update_plane(struct intel_plane *plane, > spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); > } > > +void > +skl_update_plane(struct intel_plane *plane, > + const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state *plane_state) > +{ > + skl_program_plane(plane, crtc_state, plane_state, > + !!plane_state->linked_plane, false, The !!linked thing is a bit magicy. I'd probably forget what it means every single time. So IMO deserves to be written out in a bit more verbose way and/or accompanied by a comment. > + plane_state->ctl); > +} > + > +static void > +icl_update_slave(struct intel_plane *plane, > + const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state *plane_state) > +{ > + skl_program_plane(plane, crtc_state, plane_state, 0, true, > + plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE); So that one bit is the only difference (apart from the obvious PLANE_SURF/STRIDE/OFFSET? No need to deal with the chroma vs. luma size difference etc? > +} > + > void > skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) > { > @@ -1775,6 +1796,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, > const uint64_t *modifiers; > unsigned int supported_rotations; > int num_plane_formats; > + enum plane_id plane_id = PLANE_SPRITE0 + plane; > int ret; > > intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); > @@ -1794,16 +1816,18 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, > state->scaler_id = -1; > > intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, > - PLANE_SPRITE0 + plane); > + plane_id); > > intel_plane->max_stride = skl_plane_max_stride; > intel_plane->update_plane = skl_update_plane; > + if (icl_is_nv12_y_plane(plane_id)) > + intel_plane->update_slave = icl_update_slave; > 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)) { > + plane_id)) { > plane_formats = skl_planar_formats; > num_plane_formats = ARRAY_SIZE(skl_planar_formats); > } else { > @@ -1877,7 +1901,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, > > intel_plane->pipe = pipe; > intel_plane->i9xx_plane = plane; > - intel_plane->id = PLANE_SPRITE0 + plane; > + intel_plane->id = plane_id; > intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id); > > possible_crtcs = (1 << pipe); > -- > 2.18.0 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Op 21-09-18 om 21:01 schreef Ville Syrjälä: > On Fri, Sep 21, 2018 at 07:39:44PM +0200, Maarten Lankhorst wrote: >> The UV plane is the master plane that does all color correction etc. >> It needs to be programmed with the dimensions for color plane 1 (UV). >> >> The Y plane just feeds the Y pixels to it. Program the scaler from the >> master only, and set PLANE_CTL_YUV420_Y_PLANE on the slave plane. >> >> Changes since v1: >> - Make a common skl_program_plane, and use it for both plane updates. >> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> >> --- >> drivers/gpu/drm/i915/i915_reg.h | 1 + >> drivers/gpu/drm/i915/intel_sprite.c | 50 +++++++++++++++++++++-------- >> 2 files changed, 38 insertions(+), 13 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h >> index b614a06b66c4..a3129a4c15cc 100644 >> --- a/drivers/gpu/drm/i915/i915_reg.h >> +++ b/drivers/gpu/drm/i915/i915_reg.h >> @@ -6511,6 +6511,7 @@ enum { >> #define PLANE_CTL_KEY_ENABLE_DESTINATION (2 << 21) >> #define PLANE_CTL_ORDER_BGRX (0 << 20) >> #define PLANE_CTL_ORDER_RGBX (1 << 20) >> +#define PLANE_CTL_YUV420_Y_PLANE (1 << 19) >> #define PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709 (1 << 18) >> #define PLANE_CTL_YUV422_ORDER_MASK (0x3 << 16) >> #define PLANE_CTL_YUV422_YUYV (0 << 16) >> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c >> index c4e05b0b60bf..708d2dfd59d7 100644 >> --- a/drivers/gpu/drm/i915/intel_sprite.c >> +++ b/drivers/gpu/drm/i915/intel_sprite.c >> @@ -339,23 +339,23 @@ skl_program_scaler(struct drm_i915_private *dev_priv, >> ((crtc_w + 1) << 16)|(crtc_h + 1)); >> } >> >> -void >> -skl_update_plane(struct intel_plane *plane, >> - const struct intel_crtc_state *crtc_state, >> - const struct intel_plane_state *plane_state) >> +static void >> +skl_program_plane(struct intel_plane *plane, >> + const struct intel_crtc_state *crtc_state, >> + const struct intel_plane_state *plane_state, >> + int color_plane, bool slave, u32 plane_ctl) >> { >> struct drm_i915_private *dev_priv = to_i915(plane->base.dev); >> enum plane_id plane_id = plane->id; >> enum pipe pipe = plane->pipe; >> - u32 plane_ctl = plane_state->ctl; >> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; >> - u32 surf_addr = plane_state->color_plane[0].offset; >> - u32 stride = skl_plane_stride(plane_state, 0); >> + u32 surf_addr = plane_state->color_plane[color_plane].offset; >> + u32 stride = skl_plane_stride(plane_state, color_plane); >> u32 aux_stride = skl_plane_stride(plane_state, 1); >> int crtc_x = plane_state->base.dst.x1; >> int crtc_y = plane_state->base.dst.y1; >> - uint32_t x = plane_state->color_plane[0].x; >> - uint32_t y = plane_state->color_plane[0].y; >> + uint32_t x = plane_state->color_plane[color_plane].x; >> + uint32_t y = plane_state->color_plane[color_plane].y; >> uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; >> uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; >> struct intel_plane *linked = plane_state->linked_plane; >> @@ -409,7 +409,9 @@ skl_update_plane(struct intel_plane *plane, >> >> /* program plane scaler */ >> if (plane_state->scaler_id >= 0) { >> - skl_program_scaler(dev_priv, plane, crtc_state, plane_state); >> + if (!slave) >> + skl_program_scaler(dev_priv, plane, >> + crtc_state, plane_state); >> >> I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0); >> } else { >> @@ -424,6 +426,25 @@ skl_update_plane(struct intel_plane *plane, >> spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); >> } >> >> +void >> +skl_update_plane(struct intel_plane *plane, >> + const struct intel_crtc_state *crtc_state, >> + const struct intel_plane_state *plane_state) >> +{ >> + skl_program_plane(plane, crtc_state, plane_state, >> + !!plane_state->linked_plane, false, > The !!linked thing is a bit magicy. I'd probably forget what it means > every single time. So IMO deserves to be written out in a bit more > verbose way and/or accompanied by a comment. I'll just make a variable int color_plane = plane_state->linked_plane ? 1 : 0? >> + plane_state->ctl); >> +} >> + >> +static void >> +icl_update_slave(struct intel_plane *plane, >> + const struct intel_crtc_state *crtc_state, >> + const struct intel_plane_state *plane_state) >> +{ >> + skl_program_plane(plane, crtc_state, plane_state, 0, true, >> + plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE); > So that one bit is the only difference (apart from the obvious > PLANE_SURF/STRIDE/OFFSET? No need to deal with the chroma vs. luma > size difference etc? Yes, and all color management is ignored on the Y plane. Still there doesn't seem to be any harm in programming it, so *shrug*. Only not so nice thing is I found a CRC mismatch when using chroma upsampling + scaling vs just using the chroma upsampling. Seems to be a small ~1 or 2 pixel difference in 10 bit. Need to investigate it a bit more, but with 8 bits you don't notice it. Just an annoying crc mismatch. :) ~Maarten
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b614a06b66c4..a3129a4c15cc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6511,6 +6511,7 @@ enum { #define PLANE_CTL_KEY_ENABLE_DESTINATION (2 << 21) #define PLANE_CTL_ORDER_BGRX (0 << 20) #define PLANE_CTL_ORDER_RGBX (1 << 20) +#define PLANE_CTL_YUV420_Y_PLANE (1 << 19) #define PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709 (1 << 18) #define PLANE_CTL_YUV422_ORDER_MASK (0x3 << 16) #define PLANE_CTL_YUV422_YUYV (0 << 16) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index c4e05b0b60bf..708d2dfd59d7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -339,23 +339,23 @@ skl_program_scaler(struct drm_i915_private *dev_priv, ((crtc_w + 1) << 16)|(crtc_h + 1)); } -void -skl_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +static void +skl_program_plane(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state, + int color_plane, bool slave, u32 plane_ctl) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - u32 plane_ctl = plane_state->ctl; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; - u32 surf_addr = plane_state->color_plane[0].offset; - u32 stride = skl_plane_stride(plane_state, 0); + u32 surf_addr = plane_state->color_plane[color_plane].offset; + u32 stride = skl_plane_stride(plane_state, color_plane); u32 aux_stride = skl_plane_stride(plane_state, 1); int crtc_x = plane_state->base.dst.x1; int crtc_y = plane_state->base.dst.y1; - uint32_t x = plane_state->color_plane[0].x; - uint32_t y = plane_state->color_plane[0].y; + uint32_t x = plane_state->color_plane[color_plane].x; + uint32_t y = plane_state->color_plane[color_plane].y; uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; struct intel_plane *linked = plane_state->linked_plane; @@ -409,7 +409,9 @@ skl_update_plane(struct intel_plane *plane, /* program plane scaler */ if (plane_state->scaler_id >= 0) { - skl_program_scaler(dev_priv, plane, crtc_state, plane_state); + if (!slave) + skl_program_scaler(dev_priv, plane, + crtc_state, plane_state); I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0); } else { @@ -424,6 +426,25 @@ skl_update_plane(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +void +skl_update_plane(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + skl_program_plane(plane, crtc_state, plane_state, + !!plane_state->linked_plane, false, + plane_state->ctl); +} + +static void +icl_update_slave(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + skl_program_plane(plane, crtc_state, plane_state, 0, true, + plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE); +} + void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) { @@ -1775,6 +1796,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, const uint64_t *modifiers; unsigned int supported_rotations; int num_plane_formats; + enum plane_id plane_id = PLANE_SPRITE0 + plane; int ret; intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); @@ -1794,16 +1816,18 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, state->scaler_id = -1; intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, - PLANE_SPRITE0 + plane); + plane_id); intel_plane->max_stride = skl_plane_max_stride; intel_plane->update_plane = skl_update_plane; + if (icl_is_nv12_y_plane(plane_id)) + intel_plane->update_slave = icl_update_slave; 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)) { + plane_id)) { plane_formats = skl_planar_formats; num_plane_formats = ARRAY_SIZE(skl_planar_formats); } else { @@ -1877,7 +1901,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->pipe = pipe; intel_plane->i9xx_plane = plane; - intel_plane->id = PLANE_SPRITE0 + plane; + intel_plane->id = plane_id; intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id); possible_crtcs = (1 << pipe);
The UV plane is the master plane that does all color correction etc. It needs to be programmed with the dimensions for color plane 1 (UV). The Y plane just feeds the Y pixels to it. Program the scaler from the master only, and set PLANE_CTL_YUV420_Y_PLANE on the slave plane. Changes since v1: - Make a common skl_program_plane, and use it for both plane updates. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_sprite.c | 50 +++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 13 deletions(-)