diff options
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 75 |
1 files changed, 44 insertions, 31 deletions
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index b9903c90f5d8..39416bcd880e 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #define LAYER_COMP_MASK (0x3 << 12) | 36 | #define LAYER_COMP_MASK (0x3 << 12) |
| 37 | #define LAYER_COMP_PIXEL (0x3 << 12) | 37 | #define LAYER_COMP_PIXEL (0x3 << 12) |
| 38 | #define LAYER_COMP_PLANE (0x2 << 12) | 38 | #define LAYER_COMP_PLANE (0x2 << 12) |
| 39 | #define LAYER_PMUL_ENABLE (0x1 << 14) | ||
| 39 | #define LAYER_ALPHA_OFFSET (16) | 40 | #define LAYER_ALPHA_OFFSET (16) |
| 40 | #define LAYER_ALPHA_MASK (0xff) | 41 | #define LAYER_ALPHA_MASK (0xff) |
| 41 | #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) | 42 | #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) |
| @@ -180,6 +181,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
| 180 | struct malidp_plane_state *ms = to_malidp_plane_state(state); | 181 | struct malidp_plane_state *ms = to_malidp_plane_state(state); |
| 181 | bool rotated = state->rotation & MALIDP_ROTATED_MASK; | 182 | bool rotated = state->rotation & MALIDP_ROTATED_MASK; |
| 182 | struct drm_framebuffer *fb; | 183 | struct drm_framebuffer *fb; |
| 184 | u16 pixel_alpha = state->pixel_blend_mode; | ||
| 183 | int i, ret; | 185 | int i, ret; |
| 184 | 186 | ||
| 185 | if (!state->crtc || !state->fb) | 187 | if (!state->crtc || !state->fb) |
| @@ -242,6 +244,12 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
| 242 | ms->rotmem_size = val; | 244 | ms->rotmem_size = val; |
| 243 | } | 245 | } |
| 244 | 246 | ||
| 247 | /* HW can't support plane + pixel blending */ | ||
| 248 | if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && | ||
| 249 | (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) && | ||
| 250 | fb->format->has_alpha) | ||
| 251 | return -EINVAL; | ||
| 252 | |||
| 245 | return 0; | 253 | return 0; |
| 246 | } | 254 | } |
| 247 | 255 | ||
| @@ -323,17 +331,19 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
| 323 | { | 331 | { |
| 324 | struct malidp_plane *mp; | 332 | struct malidp_plane *mp; |
| 325 | struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); | 333 | struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); |
| 334 | struct drm_plane_state *state = plane->state; | ||
| 335 | u16 pixel_alpha = state->pixel_blend_mode; | ||
| 336 | u8 plane_alpha = state->alpha >> 8; | ||
| 326 | u32 src_w, src_h, dest_w, dest_h, val; | 337 | u32 src_w, src_h, dest_w, dest_h, val; |
| 327 | int i; | 338 | int i; |
| 328 | bool format_has_alpha = plane->state->fb->format->has_alpha; | ||
| 329 | 339 | ||
| 330 | mp = to_malidp_plane(plane); | 340 | mp = to_malidp_plane(plane); |
| 331 | 341 | ||
| 332 | /* convert src values from Q16 fixed point to integer */ | 342 | /* convert src values from Q16 fixed point to integer */ |
| 333 | src_w = plane->state->src_w >> 16; | 343 | src_w = state->src_w >> 16; |
| 334 | src_h = plane->state->src_h >> 16; | 344 | src_h = state->src_h >> 16; |
| 335 | dest_w = plane->state->crtc_w; | 345 | dest_w = state->crtc_w; |
| 336 | dest_h = plane->state->crtc_h; | 346 | dest_h = state->crtc_h; |
| 337 | 347 | ||
| 338 | val = malidp_hw_read(mp->hwdev, mp->layer->base); | 348 | val = malidp_hw_read(mp->hwdev, mp->layer->base); |
| 339 | val = (val & ~LAYER_FORMAT_MASK) | ms->format; | 349 | val = (val & ~LAYER_FORMAT_MASK) | ms->format; |
| @@ -342,14 +352,14 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
| 342 | for (i = 0; i < ms->n_planes; i++) { | 352 | for (i = 0; i < ms->n_planes; i++) { |
| 343 | /* calculate the offset for the layer's plane registers */ | 353 | /* calculate the offset for the layer's plane registers */ |
| 344 | u16 ptr = mp->layer->ptr + (i << 4); | 354 | u16 ptr = mp->layer->ptr + (i << 4); |
| 345 | dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, | 355 | dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb, |
| 346 | plane->state, i); | 356 | state, i); |
| 347 | 357 | ||
| 348 | malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); | 358 | malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); |
| 349 | malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); | 359 | malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); |
| 350 | } | 360 | } |
| 351 | malidp_de_set_plane_pitches(mp, ms->n_planes, | 361 | malidp_de_set_plane_pitches(mp, ms->n_planes, |
| 352 | plane->state->fb->pitches); | 362 | state->fb->pitches); |
| 353 | 363 | ||
| 354 | if ((plane->state->color_encoding != old_state->color_encoding) || | 364 | if ((plane->state->color_encoding != old_state->color_encoding) || |
| 355 | (plane->state->color_range != old_state->color_range)) | 365 | (plane->state->color_range != old_state->color_range)) |
| @@ -362,8 +372,8 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
| 362 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), | 372 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), |
| 363 | mp->layer->base + MALIDP_LAYER_COMP_SIZE); | 373 | mp->layer->base + MALIDP_LAYER_COMP_SIZE); |
| 364 | 374 | ||
| 365 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) | | 375 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) | |
| 366 | LAYER_V_VAL(plane->state->crtc_y), | 376 | LAYER_V_VAL(state->crtc_y), |
| 367 | mp->layer->base + MALIDP_LAYER_OFFSET); | 377 | mp->layer->base + MALIDP_LAYER_OFFSET); |
| 368 | 378 | ||
| 369 | if (mp->layer->id == DE_SMART) { | 379 | if (mp->layer->id == DE_SMART) { |
| @@ -383,38 +393,35 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
| 383 | val &= ~LAYER_ROT_MASK; | 393 | val &= ~LAYER_ROT_MASK; |
| 384 | 394 | ||
| 385 | /* setup the rotation and axis flip bits */ | 395 | /* setup the rotation and axis flip bits */ |
| 386 | if (plane->state->rotation & DRM_MODE_ROTATE_MASK) | 396 | if (state->rotation & DRM_MODE_ROTATE_MASK) |
| 387 | val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << | 397 | val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << |
| 388 | LAYER_ROT_OFFSET; | 398 | LAYER_ROT_OFFSET; |
| 389 | if (plane->state->rotation & DRM_MODE_REFLECT_X) | 399 | if (state->rotation & DRM_MODE_REFLECT_X) |
| 390 | val |= LAYER_H_FLIP; | 400 | val |= LAYER_H_FLIP; |
| 391 | if (plane->state->rotation & DRM_MODE_REFLECT_Y) | 401 | if (state->rotation & DRM_MODE_REFLECT_Y) |
| 392 | val |= LAYER_V_FLIP; | 402 | val |= LAYER_V_FLIP; |
| 393 | 403 | ||
| 394 | val &= ~LAYER_COMP_MASK; | 404 | val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff)); |
| 395 | if (format_has_alpha) { | ||
| 396 | |||
| 397 | /* | ||
| 398 | * always enable pixel alpha blending until we have a way | ||
| 399 | * to change blend modes | ||
| 400 | */ | ||
| 401 | val |= LAYER_COMP_PIXEL; | ||
| 402 | } else { | ||
| 403 | 405 | ||
| 404 | /* | 406 | if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { |
| 405 | * do not enable pixel alpha blending as the color channel | ||
| 406 | * does not have any alpha information | ||
| 407 | */ | ||
| 408 | val |= LAYER_COMP_PLANE; | 407 | val |= LAYER_COMP_PLANE; |
| 409 | 408 | } else if (state->fb->format->has_alpha) { | |
| 410 | /* Set layer alpha coefficient to 0xff ie fully opaque */ | 409 | /* We only care about blend mode if the format has alpha */ |
| 411 | val |= LAYER_ALPHA(0xff); | 410 | switch (pixel_alpha) { |
| 411 | case DRM_MODE_BLEND_PREMULTI: | ||
| 412 | val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE; | ||
| 413 | break; | ||
| 414 | case DRM_MODE_BLEND_COVERAGE: | ||
| 415 | val |= LAYER_COMP_PIXEL; | ||
| 416 | break; | ||
| 417 | } | ||
| 412 | } | 418 | } |
| 419 | val |= LAYER_ALPHA(plane_alpha); | ||
| 413 | 420 | ||
| 414 | val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); | 421 | val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); |
| 415 | if (plane->state->crtc) { | 422 | if (state->crtc) { |
| 416 | struct malidp_crtc_state *m = | 423 | struct malidp_crtc_state *m = |
| 417 | to_malidp_crtc_state(plane->state->crtc->state); | 424 | to_malidp_crtc_state(state->crtc->state); |
| 418 | 425 | ||
| 419 | if (m->scaler_config.scale_enable && | 426 | if (m->scaler_config.scale_enable && |
| 420 | m->scaler_config.plane_src_id == mp->layer->id) | 427 | m->scaler_config.plane_src_id == mp->layer->id) |
| @@ -453,6 +460,9 @@ int malidp_de_planes_init(struct drm_device *drm) | |||
| 453 | unsigned long crtcs = 1 << drm->mode_config.num_crtc; | 460 | unsigned long crtcs = 1 << drm->mode_config.num_crtc; |
| 454 | unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | | 461 | unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | |
| 455 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; | 462 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; |
| 463 | unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | | ||
| 464 | BIT(DRM_MODE_BLEND_PREMULTI) | | ||
| 465 | BIT(DRM_MODE_BLEND_COVERAGE); | ||
| 456 | u32 *formats; | 466 | u32 *formats; |
| 457 | int ret, i, j, n; | 467 | int ret, i, j, n; |
| 458 | 468 | ||
| @@ -490,6 +500,9 @@ int malidp_de_planes_init(struct drm_device *drm) | |||
| 490 | plane->hwdev = malidp->dev; | 500 | plane->hwdev = malidp->dev; |
| 491 | plane->layer = &map->layers[i]; | 501 | plane->layer = &map->layers[i]; |
| 492 | 502 | ||
| 503 | drm_plane_create_alpha_property(&plane->base); | ||
| 504 | drm_plane_create_blend_mode_property(&plane->base, blend_caps); | ||
| 505 | |||
| 493 | if (id == DE_SMART) { | 506 | if (id == DE_SMART) { |
| 494 | /* Skip the features which the SMART layer doesn't have. */ | 507 | /* Skip the features which the SMART layer doesn't have. */ |
| 495 | continue; | 508 | continue; |
