Message ID | 1527679434-13228-3-git-send-email-lowry.li@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Lowry, On Wed, May 30, 2018 at 07:23:54PM +0800, Lowry Li wrote: >Check the pixel blending mode and plane alpha value when >do the plane_check. Mali DP supports blending the current plane >with the background either based on the pixel alpha blending >mode or by using the layer's alpha value, but not both at the >same time. If both case, plane_check will return failed. > >Set the HW when doing plane_update accordingly. If plane alpha >is the 0xffff, set the PREM bit accordingly. If not we'd set >ALPHA bit as zero and layer alpha value. The code looks correct - but the description of the PREM bit seems wrong here. Did you mean "set the pixel blending bits accordingly"? With that fixed: Reviewed-by: Brian Starkey <brian.starkey@arm.com> > >Signed-off-by: Lowry Li <lowry.li@arm.com> >--- > drivers/gpu/drm/arm/malidp_planes.c | 76 +++++++++++++++++++++---------------- > 1 file changed, 44 insertions(+), 32 deletions(-) > >diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c >index 7a44897..daa3f4f 100644 >--- a/drivers/gpu/drm/arm/malidp_planes.c >+++ b/drivers/gpu/drm/arm/malidp_planes.c >@@ -35,6 +35,7 @@ > #define LAYER_COMP_MASK (0x3 << 12) > #define LAYER_COMP_PIXEL (0x3 << 12) > #define LAYER_COMP_PLANE (0x2 << 12) >+#define LAYER_PMUL_ENABLE (0x1 << 14) > #define LAYER_ALPHA_OFFSET (16) > #define LAYER_ALPHA_MASK (0xff) > #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) >@@ -182,6 +183,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, > struct malidp_plane_state *ms = to_malidp_plane_state(state); > bool rotated = state->rotation & MALIDP_ROTATED_MASK; > struct drm_framebuffer *fb; >+ u16 pixel_alpha = state->pixel_blend_mode; > int i, ret; > > if (!state->crtc || !state->fb) >@@ -244,6 +246,11 @@ static int malidp_de_plane_check(struct drm_plane *plane, > ms->rotmem_size = val; > } > >+ /* HW can't support plane + pixel blending */ >+ if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && >+ (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE)) >+ return -EINVAL; >+ > return 0; > } > >@@ -325,31 +332,33 @@ static void malidp_de_plane_update(struct drm_plane *plane, > { > struct malidp_plane *mp; > struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); >+ struct drm_plane_state *state = plane->state; >+ u16 pixel_alpha = state->pixel_blend_mode; >+ u8 plane_alpha = state->alpha >> 8; > u32 src_w, src_h, dest_w, dest_h, val; > int i; >- bool format_has_alpha = plane->state->fb->format->has_alpha; > > mp = to_malidp_plane(plane); > > /* convert src values from Q16 fixed point to integer */ >- src_w = plane->state->src_w >> 16; >- src_h = plane->state->src_h >> 16; >- dest_w = plane->state->crtc_w; >- dest_h = plane->state->crtc_h; >+ src_w = state->src_w >> 16; >+ src_h = state->src_h >> 16; >+ dest_w = state->crtc_w; >+ dest_h = state->crtc_h; > > malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); > > for (i = 0; i < ms->n_planes; i++) { > /* calculate the offset for the layer's plane registers */ > u16 ptr = mp->layer->ptr + (i << 4); >- dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, >- plane->state, i); >+ dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb, >+ state, i); > > malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); > malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); > } > malidp_de_set_plane_pitches(mp, ms->n_planes, >- plane->state->fb->pitches); >+ state->fb->pitches); > > if ((plane->state->color_encoding != old_state->color_encoding) || > (plane->state->color_range != old_state->color_range)) >@@ -362,8 +371,8 @@ static void malidp_de_plane_update(struct drm_plane *plane, > malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), > mp->layer->base + MALIDP_LAYER_COMP_SIZE); > >- malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) | >- LAYER_V_VAL(plane->state->crtc_y), >+ malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) | >+ LAYER_V_VAL(state->crtc_y), > mp->layer->base + MALIDP_LAYER_OFFSET); > > if (mp->layer->id == DE_SMART) >@@ -376,38 +385,35 @@ static void malidp_de_plane_update(struct drm_plane *plane, > val &= ~LAYER_ROT_MASK; > > /* setup the rotation and axis flip bits */ >- if (plane->state->rotation & DRM_MODE_ROTATE_MASK) >+ if (state->rotation & DRM_MODE_ROTATE_MASK) > val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << > LAYER_ROT_OFFSET; >- if (plane->state->rotation & DRM_MODE_REFLECT_X) >+ if (state->rotation & DRM_MODE_REFLECT_X) > val |= LAYER_H_FLIP; >- if (plane->state->rotation & DRM_MODE_REFLECT_Y) >+ if (state->rotation & DRM_MODE_REFLECT_Y) > val |= LAYER_V_FLIP; > >- val &= ~LAYER_COMP_MASK; >- if (format_has_alpha) { >- >- /* >- * always enable pixel alpha blending until we have a way >- * to change blend modes >- */ >- val |= LAYER_COMP_PIXEL; >- } else { >- >- /* >- * do not enable pixel alpha blending as the color channel >- * does not have any alpha information >- */ >- val |= LAYER_COMP_PLANE; >- >- /* Set layer alpha coefficient to 0xff ie fully opaque */ >+ val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE); >+ >+ if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { >+ val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha); >+ } else if (state->fb->format->has_alpha) { >+ /* We only care about blend mode if the format has alpha */ >+ switch (pixel_alpha) { >+ case DRM_MODE_BLEND_PREMULTI: >+ val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE; >+ break; >+ case DRM_MODE_BLEND_COVERAGE: >+ val |= LAYER_COMP_PIXEL; >+ break; >+ } > val |= LAYER_ALPHA(0xff); > } > > val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); >- if (plane->state->crtc) { >+ if (state->crtc) { > struct malidp_crtc_state *m = >- to_malidp_crtc_state(plane->state->crtc->state); >+ to_malidp_crtc_state(state->crtc->state); > > if (m->scaler_config.scale_enable && > m->scaler_config.plane_src_id == mp->layer->id) >@@ -446,6 +452,9 @@ int malidp_de_planes_init(struct drm_device *drm) > unsigned long crtcs = 1 << drm->mode_config.num_crtc; > unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | > DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; >+ unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | >+ BIT(DRM_MODE_BLEND_PREMULTI) | >+ BIT(DRM_MODE_BLEND_COVERAGE); > u32 *formats; > int ret, i, j, n; > >@@ -498,6 +507,9 @@ int malidp_de_planes_init(struct drm_device *drm) > malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, > plane->layer->base + MALIDP_LAYER_COMPOSE); > >+ drm_plane_create_alpha_property(&plane->base); >+ drm_plane_create_blend_mode_property(&plane->base, blend_caps); >+ > /* Attach the YUV->RGB property only to video layers */ > if (id & (DE_VIDEO1 | DE_VIDEO2)) { > /* default encoding for YUV->RGB is BT601 NARROW */ >-- >1.9.1 >
On Wed, May 30, 2018 at 02:34:33PM +0100, Brian Starkey wrote: > Hi Lowry, > > On Wed, May 30, 2018 at 07:23:54PM +0800, Lowry Li wrote: > >Check the pixel blending mode and plane alpha value when > >do the plane_check. Mali DP supports blending the current plane > >with the background either based on the pixel alpha blending > >mode or by using the layer's alpha value, but not both at the > >same time. If both case, plane_check will return failed. > > > >Set the HW when doing plane_update accordingly. If plane alpha > >is the 0xffff, set the PREM bit accordingly. If not we'd set > >ALPHA bit as zero and layer alpha value. > > The code looks correct - but the description of the PREM bit seems > wrong here. Did you mean "set the pixel blending bits accordingly"? > > With that fixed: > > Reviewed-by: Brian Starkey <brian.starkey@arm.com> > Hi Brian, PREM bit is PREMULTI bit to be set premulti or coverage bit accordingly. But yes, I think I'd change to use "set pixel blending bits accordingly" to make it entirety :) Thanks for the review. > > > >Signed-off-by: Lowry Li <lowry.li@arm.com> > >--- > >drivers/gpu/drm/arm/malidp_planes.c | 76 +++++++++++++++++++++---------------- > >1 file changed, 44 insertions(+), 32 deletions(-) > > > >diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c > >index 7a44897..daa3f4f 100644 > >--- a/drivers/gpu/drm/arm/malidp_planes.c > >+++ b/drivers/gpu/drm/arm/malidp_planes.c > >@@ -35,6 +35,7 @@ > >#define LAYER_COMP_MASK (0x3 << 12) > >#define LAYER_COMP_PIXEL (0x3 << 12) > >#define LAYER_COMP_PLANE (0x2 << 12) > >+#define LAYER_PMUL_ENABLE (0x1 << 14) > >#define LAYER_ALPHA_OFFSET (16) > >#define LAYER_ALPHA_MASK (0xff) > >#define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) > >@@ -182,6 +183,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, > > struct malidp_plane_state *ms = to_malidp_plane_state(state); > > bool rotated = state->rotation & MALIDP_ROTATED_MASK; > > struct drm_framebuffer *fb; > >+ u16 pixel_alpha = state->pixel_blend_mode; > > int i, ret; > > > > if (!state->crtc || !state->fb) > >@@ -244,6 +246,11 @@ static int malidp_de_plane_check(struct drm_plane *plane, > > ms->rotmem_size = val; > > } > > > >+ /* HW can't support plane + pixel blending */ > >+ if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && > >+ (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE)) > >+ return -EINVAL; > >+ > > return 0; > >} > > > >@@ -325,31 +332,33 @@ static void malidp_de_plane_update(struct drm_plane *plane, > >{ > > struct malidp_plane *mp; > > struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); > >+ struct drm_plane_state *state = plane->state; > >+ u16 pixel_alpha = state->pixel_blend_mode; > >+ u8 plane_alpha = state->alpha >> 8; > > u32 src_w, src_h, dest_w, dest_h, val; > > int i; > >- bool format_has_alpha = plane->state->fb->format->has_alpha; > > > > mp = to_malidp_plane(plane); > > > > /* convert src values from Q16 fixed point to integer */ > >- src_w = plane->state->src_w >> 16; > >- src_h = plane->state->src_h >> 16; > >- dest_w = plane->state->crtc_w; > >- dest_h = plane->state->crtc_h; > >+ src_w = state->src_w >> 16; > >+ src_h = state->src_h >> 16; > >+ dest_w = state->crtc_w; > >+ dest_h = state->crtc_h; > > > > malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); > > > > for (i = 0; i < ms->n_planes; i++) { > > /* calculate the offset for the layer's plane registers */ > > u16 ptr = mp->layer->ptr + (i << 4); > >- dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, > >- plane->state, i); > >+ dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb, > >+ state, i); > > > > malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); > > malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); > > } > > malidp_de_set_plane_pitches(mp, ms->n_planes, > >- plane->state->fb->pitches); > >+ state->fb->pitches); > > > > if ((plane->state->color_encoding != old_state->color_encoding) || > > (plane->state->color_range != old_state->color_range)) > >@@ -362,8 +371,8 @@ static void malidp_de_plane_update(struct drm_plane *plane, > > malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), > > mp->layer->base + MALIDP_LAYER_COMP_SIZE); > > > >- malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) | > >- LAYER_V_VAL(plane->state->crtc_y), > >+ malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) | > >+ LAYER_V_VAL(state->crtc_y), > > mp->layer->base + MALIDP_LAYER_OFFSET); > > > > if (mp->layer->id == DE_SMART) > >@@ -376,38 +385,35 @@ static void malidp_de_plane_update(struct drm_plane *plane, > > val &= ~LAYER_ROT_MASK; > > > > /* setup the rotation and axis flip bits */ > >- if (plane->state->rotation & DRM_MODE_ROTATE_MASK) > >+ if (state->rotation & DRM_MODE_ROTATE_MASK) > > val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << > > LAYER_ROT_OFFSET; > >- if (plane->state->rotation & DRM_MODE_REFLECT_X) > >+ if (state->rotation & DRM_MODE_REFLECT_X) > > val |= LAYER_H_FLIP; > >- if (plane->state->rotation & DRM_MODE_REFLECT_Y) > >+ if (state->rotation & DRM_MODE_REFLECT_Y) > > val |= LAYER_V_FLIP; > > > >- val &= ~LAYER_COMP_MASK; > >- if (format_has_alpha) { > >- > >- /* > >- * always enable pixel alpha blending until we have a way > >- * to change blend modes > >- */ > >- val |= LAYER_COMP_PIXEL; > >- } else { > >- > >- /* > >- * do not enable pixel alpha blending as the color channel > >- * does not have any alpha information > >- */ > >- val |= LAYER_COMP_PLANE; > >- > >- /* Set layer alpha coefficient to 0xff ie fully opaque */ > >+ val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE); > >+ > >+ if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { > >+ val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha); > >+ } else if (state->fb->format->has_alpha) { > >+ /* We only care about blend mode if the format has alpha */ > >+ switch (pixel_alpha) { > >+ case DRM_MODE_BLEND_PREMULTI: > >+ val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE; > >+ break; > >+ case DRM_MODE_BLEND_COVERAGE: > >+ val |= LAYER_COMP_PIXEL; > >+ break; > >+ } > > val |= LAYER_ALPHA(0xff); > > } > > > > val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); > >- if (plane->state->crtc) { > >+ if (state->crtc) { > > struct malidp_crtc_state *m = > >- to_malidp_crtc_state(plane->state->crtc->state); > >+ to_malidp_crtc_state(state->crtc->state); > > > > if (m->scaler_config.scale_enable && > > m->scaler_config.plane_src_id == mp->layer->id) > >@@ -446,6 +452,9 @@ int malidp_de_planes_init(struct drm_device *drm) > > unsigned long crtcs = 1 << drm->mode_config.num_crtc; > > unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | > > DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; > >+ unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | > >+ BIT(DRM_MODE_BLEND_PREMULTI) | > >+ BIT(DRM_MODE_BLEND_COVERAGE); > > u32 *formats; > > int ret, i, j, n; > > > >@@ -498,6 +507,9 @@ int malidp_de_planes_init(struct drm_device *drm) > > malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, > > plane->layer->base + MALIDP_LAYER_COMPOSE); > > > >+ drm_plane_create_alpha_property(&plane->base); > >+ drm_plane_create_blend_mode_property(&plane->base, blend_caps); > >+ > > /* Attach the YUV->RGB property only to video layers */ > > if (id & (DE_VIDEO1 | DE_VIDEO2)) { > > /* default encoding for YUV->RGB is BT601 NARROW */ > >-- > >1.9.1 > >
Hi Lowry, Thank you for the patch! Yet something to improve: [auto build test ERROR on drm/drm-next] [also build test ERROR on v4.17-rc7] [cannot apply to next-20180531] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Lowry-Li/drm-blend-Add-per-plane-pixel-blend-mode-property/20180601-180033 base: git://people.freedesktop.org/~airlied/linux.git drm-next config: arm64-allmodconfig (attached as .config) compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm64 All errors (new ones prefixed by >>): drivers/gpu/drm/arm/malidp_planes.c: In function 'malidp_de_plane_check': >> drivers/gpu/drm/arm/malidp_planes.c:250:12: error: 'struct drm_plane_state' has no member named 'alpha' if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && ^~ >> drivers/gpu/drm/arm/malidp_planes.c:250:23: error: 'DRM_BLEND_ALPHA_OPAQUE' undeclared (first use in this function) if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && ^~~~~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/arm/malidp_planes.c:250:23: note: each undeclared identifier is reported only once for each function it appears in drivers/gpu/drm/arm/malidp_planes.c: In function 'malidp_de_plane_update': drivers/gpu/drm/arm/malidp_planes.c:337:24: error: 'struct drm_plane_state' has no member named 'alpha' u8 plane_alpha = state->alpha >> 8; ^~ drivers/gpu/drm/arm/malidp_planes.c:398:11: error: 'struct drm_plane_state' has no member named 'alpha' if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { ^~ drivers/gpu/drm/arm/malidp_planes.c:398:22: error: 'DRM_BLEND_ALPHA_OPAQUE' undeclared (first use in this function) if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { ^~~~~~~~~~~~~~~~~~~~~~ drivers/gpu/drm/arm/malidp_planes.c: In function 'malidp_de_planes_init': >> drivers/gpu/drm/arm/malidp_planes.c:510:3: error: implicit declaration of function 'drm_plane_create_alpha_property'; did you mean 'drm_plane_create_zpos_property'? [-Werror=implicit-function-declaration] drm_plane_create_alpha_property(&plane->base); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drm_plane_create_zpos_property cc1: some warnings being treated as errors vim +250 drivers/gpu/drm/arm/malidp_planes.c 178 179 static int malidp_de_plane_check(struct drm_plane *plane, 180 struct drm_plane_state *state) 181 { 182 struct malidp_plane *mp = to_malidp_plane(plane); 183 struct malidp_plane_state *ms = to_malidp_plane_state(state); 184 bool rotated = state->rotation & MALIDP_ROTATED_MASK; 185 struct drm_framebuffer *fb; 186 u16 pixel_alpha = state->pixel_blend_mode; 187 int i, ret; 188 189 if (!state->crtc || !state->fb) 190 return 0; 191 192 fb = state->fb; 193 194 ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map, 195 mp->layer->id, 196 fb->format->format); 197 if (ms->format == MALIDP_INVALID_FORMAT_ID) 198 return -EINVAL; 199 200 ms->n_planes = fb->format->num_planes; 201 for (i = 0; i < ms->n_planes; i++) { 202 u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated); 203 if (fb->pitches[i] & (alignment - 1)) { 204 DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", 205 fb->pitches[i], i); 206 return -EINVAL; 207 } 208 } 209 210 if ((state->crtc_w > mp->hwdev->max_line_size) || 211 (state->crtc_h > mp->hwdev->max_line_size) || 212 (state->crtc_w < mp->hwdev->min_line_size) || 213 (state->crtc_h < mp->hwdev->min_line_size)) 214 return -EINVAL; 215 216 /* 217 * DP550/650 video layers can accept 3 plane formats only if 218 * fb->pitches[1] == fb->pitches[2] since they don't have a 219 * third plane stride register. 220 */ 221 if (ms->n_planes == 3 && 222 !(mp->hwdev->hw->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) && 223 (state->fb->pitches[1] != state->fb->pitches[2])) 224 return -EINVAL; 225 226 ret = malidp_se_check_scaling(mp, state); 227 if (ret) 228 return ret; 229 230 /* packed RGB888 / BGR888 can't be rotated or flipped */ 231 if (state->rotation != DRM_MODE_ROTATE_0 && 232 (fb->format->format == DRM_FORMAT_RGB888 || 233 fb->format->format == DRM_FORMAT_BGR888)) 234 return -EINVAL; 235 236 ms->rotmem_size = 0; 237 if (state->rotation & MALIDP_ROTATED_MASK) { 238 int val; 239 240 val = mp->hwdev->hw->rotmem_required(mp->hwdev, state->crtc_h, 241 state->crtc_w, 242 fb->format->format); 243 if (val < 0) 244 return val; 245 246 ms->rotmem_size = val; 247 } 248 249 /* HW can't support plane + pixel blending */ > 250 if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && 251 (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE)) 252 return -EINVAL; 253 254 return 0; 255 } 256 257 static void malidp_de_set_plane_pitches(struct malidp_plane *mp, 258 int num_planes, unsigned int pitches[3]) 259 { 260 int i; 261 int num_strides = num_planes; 262 263 if (!mp->layer->stride_offset) 264 return; 265 266 if (num_planes == 3) 267 num_strides = (mp->hwdev->hw->features & 268 MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2; 269 270 for (i = 0; i < num_strides; ++i) 271 malidp_hw_write(mp->hwdev, pitches[i], 272 mp->layer->base + 273 mp->layer->stride_offset + i * 4); 274 } 275 276 static const s16 277 malidp_yuv2rgb_coeffs[][DRM_COLOR_RANGE_MAX][MALIDP_COLORADJ_NUM_COEFFS] = { 278 [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = { 279 1192, 0, 1634, 280 1192, -401, -832, 281 1192, 2066, 0, 282 64, 512, 512 283 }, 284 [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = { 285 1024, 0, 1436, 286 1024, -352, -731, 287 1024, 1815, 0, 288 0, 512, 512 289 }, 290 [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = { 291 1192, 0, 1836, 292 1192, -218, -546, 293 1192, 2163, 0, 294 64, 512, 512 295 }, 296 [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = { 297 1024, 0, 1613, 298 1024, -192, -479, 299 1024, 1900, 0, 300 0, 512, 512 301 }, 302 [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = { 303 1024, 0, 1476, 304 1024, -165, -572, 305 1024, 1884, 0, 306 0, 512, 512 307 }, 308 [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = { 309 1024, 0, 1510, 310 1024, -168, -585, 311 1024, 1927, 0, 312 0, 512, 512 313 } 314 }; 315 316 static void malidp_de_set_color_encoding(struct malidp_plane *plane, 317 enum drm_color_encoding enc, 318 enum drm_color_range range) 319 { 320 unsigned int i; 321 322 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { 323 /* coefficients are signed, two's complement values */ 324 malidp_hw_write(plane->hwdev, malidp_yuv2rgb_coeffs[enc][range][i], 325 plane->layer->base + plane->layer->yuv2rgb_offset + 326 i * 4); 327 } 328 } 329 330 static void malidp_de_plane_update(struct drm_plane *plane, 331 struct drm_plane_state *old_state) 332 { 333 struct malidp_plane *mp; 334 struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); 335 struct drm_plane_state *state = plane->state; 336 u16 pixel_alpha = state->pixel_blend_mode; 337 u8 plane_alpha = state->alpha >> 8; 338 u32 src_w, src_h, dest_w, dest_h, val; 339 int i; 340 341 mp = to_malidp_plane(plane); 342 343 /* convert src values from Q16 fixed point to integer */ 344 src_w = state->src_w >> 16; 345 src_h = state->src_h >> 16; 346 dest_w = state->crtc_w; 347 dest_h = state->crtc_h; 348 349 malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); 350 351 for (i = 0; i < ms->n_planes; i++) { 352 /* calculate the offset for the layer's plane registers */ 353 u16 ptr = mp->layer->ptr + (i << 4); 354 dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb, 355 state, i); 356 357 malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); 358 malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); 359 } 360 malidp_de_set_plane_pitches(mp, ms->n_planes, 361 state->fb->pitches); 362 363 if ((plane->state->color_encoding != old_state->color_encoding) || 364 (plane->state->color_range != old_state->color_range)) 365 malidp_de_set_color_encoding(mp, plane->state->color_encoding, 366 plane->state->color_range); 367 368 malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), 369 mp->layer->base + MALIDP_LAYER_SIZE); 370 371 malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), 372 mp->layer->base + MALIDP_LAYER_COMP_SIZE); 373 374 malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) | 375 LAYER_V_VAL(state->crtc_y), 376 mp->layer->base + MALIDP_LAYER_OFFSET); 377 378 if (mp->layer->id == DE_SMART) 379 malidp_hw_write(mp->hwdev, 380 LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), 381 mp->layer->base + MALIDP550_LS_R1_IN_SIZE); 382 383 /* first clear the rotation bits */ 384 val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL); 385 val &= ~LAYER_ROT_MASK; 386 387 /* setup the rotation and axis flip bits */ 388 if (state->rotation & DRM_MODE_ROTATE_MASK) 389 val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << 390 LAYER_ROT_OFFSET; 391 if (state->rotation & DRM_MODE_REFLECT_X) 392 val |= LAYER_H_FLIP; 393 if (state->rotation & DRM_MODE_REFLECT_Y) 394 val |= LAYER_V_FLIP; 395 396 val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE); 397 > 398 if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { 399 val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha); 400 } else if (state->fb->format->has_alpha) { 401 /* We only care about blend mode if the format has alpha */ 402 switch (pixel_alpha) { 403 case DRM_MODE_BLEND_PREMULTI: 404 val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE; 405 break; 406 case DRM_MODE_BLEND_COVERAGE: 407 val |= LAYER_COMP_PIXEL; 408 break; 409 } 410 val |= LAYER_ALPHA(0xff); 411 } 412 413 val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); 414 if (state->crtc) { 415 struct malidp_crtc_state *m = 416 to_malidp_crtc_state(state->crtc->state); 417 418 if (m->scaler_config.scale_enable && 419 m->scaler_config.plane_src_id == mp->layer->id) 420 val |= LAYER_FLOWCFG(LAYER_FLOWCFG_SCALE_SE); 421 } 422 423 /* set the 'enable layer' bit */ 424 val |= LAYER_ENABLE; 425 426 malidp_hw_write(mp->hwdev, val, 427 mp->layer->base + MALIDP_LAYER_CONTROL); 428 } 429 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 7a44897..daa3f4f 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -35,6 +35,7 @@ #define LAYER_COMP_MASK (0x3 << 12) #define LAYER_COMP_PIXEL (0x3 << 12) #define LAYER_COMP_PLANE (0x2 << 12) +#define LAYER_PMUL_ENABLE (0x1 << 14) #define LAYER_ALPHA_OFFSET (16) #define LAYER_ALPHA_MASK (0xff) #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) @@ -182,6 +183,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, struct malidp_plane_state *ms = to_malidp_plane_state(state); bool rotated = state->rotation & MALIDP_ROTATED_MASK; struct drm_framebuffer *fb; + u16 pixel_alpha = state->pixel_blend_mode; int i, ret; if (!state->crtc || !state->fb) @@ -244,6 +246,11 @@ static int malidp_de_plane_check(struct drm_plane *plane, ms->rotmem_size = val; } + /* HW can't support plane + pixel blending */ + if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && + (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE)) + return -EINVAL; + return 0; } @@ -325,31 +332,33 @@ static void malidp_de_plane_update(struct drm_plane *plane, { struct malidp_plane *mp; struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); + struct drm_plane_state *state = plane->state; + u16 pixel_alpha = state->pixel_blend_mode; + u8 plane_alpha = state->alpha >> 8; u32 src_w, src_h, dest_w, dest_h, val; int i; - bool format_has_alpha = plane->state->fb->format->has_alpha; mp = to_malidp_plane(plane); /* convert src values from Q16 fixed point to integer */ - src_w = plane->state->src_w >> 16; - src_h = plane->state->src_h >> 16; - dest_w = plane->state->crtc_w; - dest_h = plane->state->crtc_h; + src_w = state->src_w >> 16; + src_h = state->src_h >> 16; + dest_w = state->crtc_w; + dest_h = state->crtc_h; malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); for (i = 0; i < ms->n_planes; i++) { /* calculate the offset for the layer's plane registers */ u16 ptr = mp->layer->ptr + (i << 4); - dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, - plane->state, i); + dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb, + state, i); malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); } malidp_de_set_plane_pitches(mp, ms->n_planes, - plane->state->fb->pitches); + state->fb->pitches); if ((plane->state->color_encoding != old_state->color_encoding) || (plane->state->color_range != old_state->color_range)) @@ -362,8 +371,8 @@ static void malidp_de_plane_update(struct drm_plane *plane, malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), mp->layer->base + MALIDP_LAYER_COMP_SIZE); - malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) | - LAYER_V_VAL(plane->state->crtc_y), + malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) | + LAYER_V_VAL(state->crtc_y), mp->layer->base + MALIDP_LAYER_OFFSET); if (mp->layer->id == DE_SMART) @@ -376,38 +385,35 @@ static void malidp_de_plane_update(struct drm_plane *plane, val &= ~LAYER_ROT_MASK; /* setup the rotation and axis flip bits */ - if (plane->state->rotation & DRM_MODE_ROTATE_MASK) + if (state->rotation & DRM_MODE_ROTATE_MASK) val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << LAYER_ROT_OFFSET; - if (plane->state->rotation & DRM_MODE_REFLECT_X) + if (state->rotation & DRM_MODE_REFLECT_X) val |= LAYER_H_FLIP; - if (plane->state->rotation & DRM_MODE_REFLECT_Y) + if (state->rotation & DRM_MODE_REFLECT_Y) val |= LAYER_V_FLIP; - val &= ~LAYER_COMP_MASK; - if (format_has_alpha) { - - /* - * always enable pixel alpha blending until we have a way - * to change blend modes - */ - val |= LAYER_COMP_PIXEL; - } else { - - /* - * do not enable pixel alpha blending as the color channel - * does not have any alpha information - */ - val |= LAYER_COMP_PLANE; - - /* Set layer alpha coefficient to 0xff ie fully opaque */ + val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE); + + if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { + val |= LAYER_COMP_PLANE | LAYER_ALPHA(plane_alpha); + } else if (state->fb->format->has_alpha) { + /* We only care about blend mode if the format has alpha */ + switch (pixel_alpha) { + case DRM_MODE_BLEND_PREMULTI: + val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE; + break; + case DRM_MODE_BLEND_COVERAGE: + val |= LAYER_COMP_PIXEL; + break; + } val |= LAYER_ALPHA(0xff); } val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); - if (plane->state->crtc) { + if (state->crtc) { struct malidp_crtc_state *m = - to_malidp_crtc_state(plane->state->crtc->state); + to_malidp_crtc_state(state->crtc->state); if (m->scaler_config.scale_enable && m->scaler_config.plane_src_id == mp->layer->id) @@ -446,6 +452,9 @@ int malidp_de_planes_init(struct drm_device *drm) unsigned long crtcs = 1 << drm->mode_config.num_crtc; unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; + unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | + BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE); u32 *formats; int ret, i, j, n; @@ -498,6 +507,9 @@ int malidp_de_planes_init(struct drm_device *drm) malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, plane->layer->base + MALIDP_LAYER_COMPOSE); + drm_plane_create_alpha_property(&plane->base); + drm_plane_create_blend_mode_property(&plane->base, blend_caps); + /* Attach the YUV->RGB property only to video layers */ if (id & (DE_VIDEO1 | DE_VIDEO2)) { /* default encoding for YUV->RGB is BT601 NARROW */
Check the pixel blending mode and plane alpha value when do the plane_check. Mali DP supports blending the current plane with the background either based on the pixel alpha blending mode or by using the layer's alpha value, but not both at the same time. If both case, plane_check will return failed. Set the HW when doing plane_update accordingly. If plane alpha is the 0xffff, set the PREM bit accordingly. If not we'd set ALPHA bit as zero and layer alpha value. Signed-off-by: Lowry Li <lowry.li@arm.com> --- drivers/gpu/drm/arm/malidp_planes.c | 76 +++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 32 deletions(-)