Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/kmb: Enable alpha blended second plane

Enable one additional plane that is alpha blended on top
of the primary plane.

This also fixes the below warnings when building with
-Warray-bounds:

drivers/gpu/drm/kmb/kmb_plane.c:135:20: warning: array subscript 3 is
above array bounds of 'struct layer_status[1]' [-Warray-bounds]
drivers/gpu/drm/kmb/kmb_plane.c:132:20: warning: array subscript 2 is
above array bounds of 'struct layer_status[1]' [-Warray-bounds]
drivers/gpu/drm/kmb/kmb_plane.c:129:20: warning: array subscript 1 is
above array bounds of 'struct layer_status[1]' [-Warray-bounds]

v2: corrected previous patch dependecies so it builds

Signed-off-by: Edmund Dea <edmund.j.dea@intel.com>
Signed-off-by: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.kernel.org/project/dri-devel/patch/20210728003126.1425028-13-anitha.chrisanthus@intel.com/
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

authored by

Edmund Dea and committed by
Maarten Lankhorst
c026565f 9e1ff307

+87 -15
+4 -4
drivers/gpu/drm/kmb/kmb_drv.c
··· 172 172 ret = drmm_mode_config_init(drm); 173 173 if (ret) 174 174 return ret; 175 - drm->mode_config.min_width = KMB_MIN_WIDTH; 176 - drm->mode_config.min_height = KMB_MIN_HEIGHT; 177 - drm->mode_config.max_width = KMB_MAX_WIDTH; 178 - drm->mode_config.max_height = KMB_MAX_HEIGHT; 175 + drm->mode_config.min_width = KMB_FB_MIN_WIDTH; 176 + drm->mode_config.min_height = KMB_FB_MIN_HEIGHT; 177 + drm->mode_config.max_width = KMB_FB_MAX_WIDTH; 178 + drm->mode_config.max_height = KMB_FB_MAX_HEIGHT; 179 179 drm->mode_config.funcs = &kmb_mode_config_funcs; 180 180 181 181 ret = kmb_setup_crtc(drm);
+5
drivers/gpu/drm/kmb/kmb_drv.h
··· 20 20 #define DRIVER_MAJOR 1 21 21 #define DRIVER_MINOR 1 22 22 23 + #define KMB_FB_MAX_WIDTH 1920 24 + #define KMB_FB_MAX_HEIGHT 1080 25 + #define KMB_FB_MIN_WIDTH 1 26 + #define KMB_FB_MIN_HEIGHT 1 27 + 23 28 #define KMB_LCD_DEFAULT_CLK 200000000 24 29 #define KMB_SYS_CLK_MHZ 500 25 30
+72 -9
drivers/gpu/drm/kmb/kmb_plane.c
··· 94 94 if (ret) 95 95 return ret; 96 96 97 - if (new_plane_state->crtc_w > KMB_MAX_WIDTH || new_plane_state->crtc_h > KMB_MAX_HEIGHT) 98 - return -EINVAL; 99 - if (new_plane_state->crtc_w < KMB_MIN_WIDTH || new_plane_state->crtc_h < KMB_MIN_HEIGHT) 97 + if (new_plane_state->crtc_w > KMB_FB_MAX_WIDTH || 98 + new_plane_state->crtc_h > KMB_FB_MAX_HEIGHT || 99 + new_plane_state->crtc_w < KMB_FB_MIN_WIDTH || 100 + new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT) 100 101 return -EINVAL; 101 102 can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); 102 103 crtc_state = ··· 278 277 kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]); 279 278 } 280 279 280 + static void kmb_plane_set_alpha(struct kmb_drm_private *kmb, 281 + const struct drm_plane_state *state, 282 + unsigned char plane_id, 283 + unsigned int *val) 284 + { 285 + u16 plane_alpha = state->alpha; 286 + u16 pixel_blend_mode = state->pixel_blend_mode; 287 + int has_alpha = state->fb->format->has_alpha; 288 + 289 + if (plane_alpha != DRM_BLEND_ALPHA_OPAQUE) 290 + *val |= LCD_LAYER_ALPHA_STATIC; 291 + 292 + if (has_alpha) { 293 + switch (pixel_blend_mode) { 294 + case DRM_MODE_BLEND_PIXEL_NONE: 295 + break; 296 + case DRM_MODE_BLEND_PREMULTI: 297 + *val |= LCD_LAYER_ALPHA_EMBED | LCD_LAYER_ALPHA_PREMULT; 298 + break; 299 + case DRM_MODE_BLEND_COVERAGE: 300 + *val |= LCD_LAYER_ALPHA_EMBED; 301 + break; 302 + default: 303 + DRM_DEBUG("Missing pixel blend mode case (%s == %ld)\n", 304 + __stringify(pixel_blend_mode), 305 + (long)pixel_blend_mode); 306 + break; 307 + } 308 + } 309 + 310 + if (plane_alpha == DRM_BLEND_ALPHA_OPAQUE && !has_alpha) { 311 + *val &= LCD_LAYER_ALPHA_DISABLED; 312 + return; 313 + } 314 + 315 + kmb_write_lcd(kmb, LCD_LAYERn_ALPHA(plane_id), plane_alpha); 316 + } 317 + 281 318 static void kmb_plane_atomic_update(struct drm_plane *plane, 282 319 struct drm_atomic_state *state) 283 320 { ··· 342 303 fb = new_plane_state->fb; 343 304 if (!fb) 344 305 return; 306 + 345 307 num_planes = fb->format->num_planes; 346 308 kmb_plane = to_kmb_plane(plane); 347 - plane_id = kmb_plane->id; 348 309 349 310 kmb = to_kmb(plane->dev); 311 + plane_id = kmb_plane->id; 350 312 351 313 spin_lock_irq(&kmb->irq_lock); 352 314 if (kmb->kmb_under_flow || kmb->kmb_flush_done) { ··· 440 400 config_csc(kmb, plane_id); 441 401 } 442 402 403 + kmb_plane_set_alpha(kmb, plane->state, plane_id, &val); 404 + 443 405 kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val); 406 + 407 + /* Configure LCD_CONTROL */ 408 + ctrl = kmb_read_lcd(kmb, LCD_CONTROL); 409 + 410 + /* Set layer blending config */ 411 + ctrl &= ~LCD_CTRL_ALPHA_ALL; 412 + ctrl |= LCD_CTRL_ALPHA_BOTTOM_VL1 | 413 + LCD_CTRL_ALPHA_BLEND_VL2; 414 + 415 + ctrl &= ~LCD_CTRL_ALPHA_BLEND_BKGND_DISABLE; 444 416 445 417 switch (plane_id) { 446 418 case LAYER_0: 447 - ctrl = LCD_CTRL_VL1_ENABLE; 419 + ctrl |= LCD_CTRL_VL1_ENABLE; 448 420 break; 449 421 case LAYER_1: 450 - ctrl = LCD_CTRL_VL2_ENABLE; 422 + ctrl |= LCD_CTRL_VL2_ENABLE; 451 423 break; 452 424 case LAYER_2: 453 - ctrl = LCD_CTRL_GL1_ENABLE; 425 + ctrl |= LCD_CTRL_GL1_ENABLE; 454 426 break; 455 427 case LAYER_3: 456 - ctrl = LCD_CTRL_GL2_ENABLE; 428 + ctrl |= LCD_CTRL_GL2_ENABLE; 457 429 break; 458 430 } 459 431 ··· 477 425 */ 478 426 ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL; 479 427 480 - kmb_set_bitmask_lcd(kmb, LCD_CONTROL, ctrl); 428 + kmb_write_lcd(kmb, LCD_CONTROL, ctrl); 481 429 482 430 /* Enable pipeline AXI read transactions for the DMA 483 431 * after setting graphics layers. This must be done ··· 542 490 enum drm_plane_type plane_type; 543 491 const u32 *plane_formats; 544 492 int num_plane_formats; 493 + unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | 494 + BIT(DRM_MODE_BLEND_PREMULTI) | 495 + BIT(DRM_MODE_BLEND_COVERAGE); 545 496 546 497 for (i = 0; i < KMB_MAX_PLANES; i++) { 547 498 plane = drmm_kzalloc(drm, sizeof(*plane), GFP_KERNEL); ··· 576 521 drm_dbg(drm, "%s : %d i=%d type=%d", 577 522 __func__, __LINE__, 578 523 i, plane_type); 524 + drm_plane_create_alpha_property(&plane->base_plane); 525 + 526 + drm_plane_create_blend_mode_property(&plane->base_plane, 527 + blend_caps); 528 + 529 + drm_plane_create_zpos_immutable_property(&plane->base_plane, i); 530 + 579 531 drm_plane_helper_add(&plane->base_plane, 580 532 &kmb_plane_helper_funcs); 533 + 581 534 if (plane_type == DRM_PLANE_TYPE_PRIMARY) { 582 535 primary = plane; 583 536 kmb->plane = plane;
+3 -2
drivers/gpu/drm/kmb/kmb_plane.h
··· 35 35 #define POSSIBLE_CRTCS 1 36 36 #define to_kmb_plane(x) container_of(x, struct kmb_plane, base_plane) 37 37 38 + #define POSSIBLE_CRTCS 1 39 + #define KMB_MAX_PLANES 2 40 + 38 41 enum layer_id { 39 42 LAYER_0, 40 43 LAYER_1, ··· 45 42 LAYER_3, 46 43 /* KMB_MAX_PLANES */ 47 44 }; 48 - 49 - #define KMB_MAX_PLANES 1 50 45 51 46 enum sub_plane_id { 52 47 Y_PLANE,
+3
drivers/gpu/drm/kmb/kmb_regs.h
··· 43 43 #define LCD_CTRL_OUTPUT_ENABLED BIT(19) 44 44 #define LCD_CTRL_BPORCH_ENABLE BIT(21) 45 45 #define LCD_CTRL_FPORCH_ENABLE BIT(22) 46 + #define LCD_CTRL_ALPHA_BLEND_BKGND_DISABLE BIT(23) 46 47 #define LCD_CTRL_PIPELINE_DMA BIT(28) 47 48 #define LCD_CTRL_VHSYNC_IDLE_LVL BIT(31) 49 + #define LCD_CTRL_ALPHA_ALL (0xff << 6) 48 50 49 51 /* interrupts */ 50 52 #define LCD_INT_STATUS (0x4 * 0x001) ··· 117 115 #define LCD_LAYER_ALPHA_EMBED BIT(5) 118 116 #define LCD_LAYER_ALPHA_COMBI (LCD_LAYER_ALPHA_STATIC | \ 119 117 LCD_LAYER_ALPHA_EMBED) 118 + #define LCD_LAYER_ALPHA_DISABLED ~(LCD_LAYER_ALPHA_COMBI) 120 119 /* RGB multiplied with alpha */ 121 120 #define LCD_LAYER_ALPHA_PREMULT BIT(6) 122 121 #define LCD_LAYER_INVERT_COL BIT(7)