Commit c026565f authored by Edmund Dea's avatar Edmund Dea Committed by Maarten Lankhorst
Browse files

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: default avatarEdmund Dea <edmund.j.dea@intel.com>
Signed-off-by: default avatarAnitha Chrisanthus <anitha.chrisanthus@intel.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.kernel.org/project/dri-devel/patch/20210728003126.1425028-13-anitha.chrisanthus@intel.com/


Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
parent 9e1ff307
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -172,10 +172,10 @@ static int kmb_setup_mode_config(struct drm_device *drm)
	ret = drmm_mode_config_init(drm);
	if (ret)
		return ret;
	drm->mode_config.min_width = KMB_MIN_WIDTH;
	drm->mode_config.min_height = KMB_MIN_HEIGHT;
	drm->mode_config.max_width = KMB_MAX_WIDTH;
	drm->mode_config.max_height = KMB_MAX_HEIGHT;
	drm->mode_config.min_width = KMB_FB_MIN_WIDTH;
	drm->mode_config.min_height = KMB_FB_MIN_HEIGHT;
	drm->mode_config.max_width = KMB_FB_MAX_WIDTH;
	drm->mode_config.max_height = KMB_FB_MAX_HEIGHT;
	drm->mode_config.funcs = &kmb_mode_config_funcs;

	ret = kmb_setup_crtc(drm);
+5 −0
Original line number Diff line number Diff line
@@ -20,6 +20,11 @@
#define DRIVER_MAJOR			1
#define DRIVER_MINOR			1

#define KMB_FB_MAX_WIDTH		1920
#define KMB_FB_MAX_HEIGHT		1080
#define KMB_FB_MIN_WIDTH		1
#define KMB_FB_MIN_HEIGHT		1

#define KMB_LCD_DEFAULT_CLK		200000000
#define KMB_SYS_CLK_MHZ			500

+72 −9
Original line number Diff line number Diff line
@@ -94,9 +94,10 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
	if (ret)
		return ret;

	if (new_plane_state->crtc_w > KMB_MAX_WIDTH || new_plane_state->crtc_h > KMB_MAX_HEIGHT)
		return -EINVAL;
	if (new_plane_state->crtc_w < KMB_MIN_WIDTH || new_plane_state->crtc_h < KMB_MIN_HEIGHT)
	if (new_plane_state->crtc_w > KMB_FB_MAX_WIDTH ||
	    new_plane_state->crtc_h > KMB_FB_MAX_HEIGHT ||
	    new_plane_state->crtc_w < KMB_FB_MIN_WIDTH ||
	    new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT)
		return -EINVAL;
	can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
	crtc_state =
@@ -277,6 +278,44 @@ static void config_csc(struct kmb_drm_private *kmb, int plane_id)
	kmb_write_lcd(kmb, LCD_LAYERn_CSC_OFF3(plane_id), csc_coef_lcd[11]);
}

static void kmb_plane_set_alpha(struct kmb_drm_private *kmb,
				const struct drm_plane_state *state,
				unsigned char plane_id,
				unsigned int *val)
{
	u16 plane_alpha = state->alpha;
	u16 pixel_blend_mode = state->pixel_blend_mode;
	int has_alpha = state->fb->format->has_alpha;

	if (plane_alpha != DRM_BLEND_ALPHA_OPAQUE)
		*val |= LCD_LAYER_ALPHA_STATIC;

	if (has_alpha) {
		switch (pixel_blend_mode) {
		case DRM_MODE_BLEND_PIXEL_NONE:
			break;
		case DRM_MODE_BLEND_PREMULTI:
			*val |= LCD_LAYER_ALPHA_EMBED | LCD_LAYER_ALPHA_PREMULT;
			break;
		case DRM_MODE_BLEND_COVERAGE:
			*val |= LCD_LAYER_ALPHA_EMBED;
			break;
		default:
			DRM_DEBUG("Missing pixel blend mode case (%s == %ld)\n",
				  __stringify(pixel_blend_mode),
				  (long)pixel_blend_mode);
			break;
		}
	}

	if (plane_alpha == DRM_BLEND_ALPHA_OPAQUE && !has_alpha) {
		*val &= LCD_LAYER_ALPHA_DISABLED;
		return;
	}

	kmb_write_lcd(kmb, LCD_LAYERn_ALPHA(plane_id), plane_alpha);
}

static void kmb_plane_atomic_update(struct drm_plane *plane,
				    struct drm_atomic_state *state)
{
@@ -303,11 +342,12 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
	fb = new_plane_state->fb;
	if (!fb)
		return;

	num_planes = fb->format->num_planes;
	kmb_plane = to_kmb_plane(plane);
	plane_id = kmb_plane->id;

	kmb = to_kmb(plane->dev);
	plane_id = kmb_plane->id;

	spin_lock_irq(&kmb->irq_lock);
	if (kmb->kmb_under_flow || kmb->kmb_flush_done) {
@@ -400,20 +440,32 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
		config_csc(kmb, plane_id);
	}

	kmb_plane_set_alpha(kmb, plane->state, plane_id, &val);

	kmb_write_lcd(kmb, LCD_LAYERn_CFG(plane_id), val);

	/* Configure LCD_CONTROL */
	ctrl = kmb_read_lcd(kmb, LCD_CONTROL);

	/* Set layer blending config */
	ctrl &= ~LCD_CTRL_ALPHA_ALL;
	ctrl |= LCD_CTRL_ALPHA_BOTTOM_VL1 |
		LCD_CTRL_ALPHA_BLEND_VL2;

	ctrl &= ~LCD_CTRL_ALPHA_BLEND_BKGND_DISABLE;

	switch (plane_id) {
	case LAYER_0:
		ctrl = LCD_CTRL_VL1_ENABLE;
		ctrl |= LCD_CTRL_VL1_ENABLE;
		break;
	case LAYER_1:
		ctrl = LCD_CTRL_VL2_ENABLE;
		ctrl |= LCD_CTRL_VL2_ENABLE;
		break;
	case LAYER_2:
		ctrl = LCD_CTRL_GL1_ENABLE;
		ctrl |= LCD_CTRL_GL1_ENABLE;
		break;
	case LAYER_3:
		ctrl = LCD_CTRL_GL2_ENABLE;
		ctrl |= LCD_CTRL_GL2_ENABLE;
		break;
	}

@@ -425,7 +477,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
	 */
	ctrl |= LCD_CTRL_VHSYNC_IDLE_LVL;

	kmb_set_bitmask_lcd(kmb, LCD_CONTROL, ctrl);
	kmb_write_lcd(kmb, LCD_CONTROL, ctrl);

	/* Enable pipeline AXI read transactions for the DMA
	 * after setting graphics layers. This must be done
@@ -490,6 +542,9 @@ struct kmb_plane *kmb_plane_init(struct drm_device *drm)
	enum drm_plane_type plane_type;
	const u32 *plane_formats;
	int num_plane_formats;
	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
				  BIT(DRM_MODE_BLEND_PREMULTI)   |
				  BIT(DRM_MODE_BLEND_COVERAGE);

	for (i = 0; i < KMB_MAX_PLANES; i++) {
		plane = drmm_kzalloc(drm, sizeof(*plane), GFP_KERNEL);
@@ -521,8 +576,16 @@ struct kmb_plane *kmb_plane_init(struct drm_device *drm)
		drm_dbg(drm, "%s : %d i=%d type=%d",
			__func__, __LINE__,
			  i, plane_type);
		drm_plane_create_alpha_property(&plane->base_plane);

		drm_plane_create_blend_mode_property(&plane->base_plane,
						     blend_caps);

		drm_plane_create_zpos_immutable_property(&plane->base_plane, i);

		drm_plane_helper_add(&plane->base_plane,
				     &kmb_plane_helper_funcs);

		if (plane_type == DRM_PLANE_TYPE_PRIMARY) {
			primary = plane;
			kmb->plane = plane;
+3 −2
Original line number Diff line number Diff line
@@ -35,6 +35,9 @@
#define POSSIBLE_CRTCS 1
#define to_kmb_plane(x) container_of(x, struct kmb_plane, base_plane)

#define POSSIBLE_CRTCS		1
#define KMB_MAX_PLANES		2

enum layer_id {
	LAYER_0,
	LAYER_1,
@@ -43,8 +46,6 @@ enum layer_id {
	/* KMB_MAX_PLANES */
};

#define KMB_MAX_PLANES 1

enum sub_plane_id {
	Y_PLANE,
	U_PLANE,
+3 −0
Original line number Diff line number Diff line
@@ -43,8 +43,10 @@
#define LCD_CTRL_OUTPUT_ENABLED			  BIT(19)
#define LCD_CTRL_BPORCH_ENABLE			  BIT(21)
#define LCD_CTRL_FPORCH_ENABLE			  BIT(22)
#define LCD_CTRL_ALPHA_BLEND_BKGND_DISABLE	  BIT(23)
#define LCD_CTRL_PIPELINE_DMA			  BIT(28)
#define LCD_CTRL_VHSYNC_IDLE_LVL		  BIT(31)
#define LCD_CTRL_ALPHA_ALL			  (0xff << 6)

/* interrupts */
#define LCD_INT_STATUS				(0x4 * 0x001)
@@ -115,6 +117,7 @@
#define LCD_LAYER_ALPHA_EMBED			BIT(5)
#define LCD_LAYER_ALPHA_COMBI			(LCD_LAYER_ALPHA_STATIC | \
						      LCD_LAYER_ALPHA_EMBED)
#define LCD_LAYER_ALPHA_DISABLED		~(LCD_LAYER_ALPHA_COMBI)
/* RGB multiplied with alpha */
#define LCD_LAYER_ALPHA_PREMULT			BIT(6)
#define LCD_LAYER_INVERT_COL			BIT(7)