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

drm/kmb: Disable change of plane parameters



Due to HW limitations, KMB cannot change height, width, or
pixel format after initial plane configuration.

v2: removed memset disp_cfg as it is already zero.

Fixes: 7f7b96a8 ("drm/kmb: Add support for KeemBay Display")
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.freedesktop.org/patch/msgid/20211013233632.471892-4-anitha.chrisanthus@intel.com


Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
parent 13047a09
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ struct kmb_drm_private {
	spinlock_t			irq_lock;
	int				irq_lcd;
	int				sys_clk_mhz;
	struct disp_cfg			init_disp_cfg[KMB_MAX_PLANES];
	struct layer_status		plane_status[KMB_MAX_PLANES];
	int				kmb_under_flow;
	int				kmb_flush_done;
+42 −1
Original line number Diff line number Diff line
@@ -67,8 +67,21 @@ static const u32 kmb_formats_v[] = {

static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
{
	struct kmb_drm_private *kmb;
	struct kmb_plane *kmb_plane = to_kmb_plane(plane);
	int i;
	int plane_id = kmb_plane->id;
	struct disp_cfg init_disp_cfg;

	kmb = to_kmb(plane->dev);
	init_disp_cfg = kmb->init_disp_cfg[plane_id];
	/* Due to HW limitations, changing pixel format after initial
	 * plane configuration is not supported.
	 */
	if (init_disp_cfg.format && init_disp_cfg.format != format) {
		drm_dbg(&kmb->drm, "Cannot change format after initial plane configuration");
		return -EINVAL;
	}
	for (i = 0; i < plane->format_count; i++) {
		if (plane->format_types[i] == format)
			return 0;
@@ -81,11 +94,17 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
{
	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
										 plane);
	struct kmb_drm_private *kmb;
	struct kmb_plane *kmb_plane = to_kmb_plane(plane);
	int plane_id = kmb_plane->id;
	struct disp_cfg init_disp_cfg;
	struct drm_framebuffer *fb;
	int ret;
	struct drm_crtc_state *crtc_state;
	bool can_position;

	kmb = to_kmb(plane->dev);
	init_disp_cfg = kmb->init_disp_cfg[plane_id];
	fb = new_plane_state->fb;
	if (!fb || !new_plane_state->crtc)
		return 0;
@@ -99,6 +118,16 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
	    new_plane_state->crtc_w < KMB_FB_MIN_WIDTH ||
	    new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT)
		return -EINVAL;

	/* Due to HW limitations, changing plane height or width after
	 * initial plane configuration is not supported.
	 */
	if ((init_disp_cfg.width && init_disp_cfg.height) &&
	    (init_disp_cfg.width != fb->width ||
	    init_disp_cfg.height != fb->height)) {
		drm_dbg(&kmb->drm, "Cannot change plane height or width after initial configuration");
		return -EINVAL;
	}
	can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
	crtc_state =
		drm_atomic_get_existing_crtc_state(state,
@@ -335,6 +364,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
	unsigned char plane_id;
	int num_planes;
	static dma_addr_t addr[MAX_SUB_PLANES];
	struct disp_cfg *init_disp_cfg;

	if (!plane || !new_plane_state || !old_plane_state)
		return;
@@ -357,7 +387,8 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
	}
	spin_unlock_irq(&kmb->irq_lock);

	src_w = (new_plane_state->src_w >> 16);
	init_disp_cfg = &kmb->init_disp_cfg[plane_id];
	src_w = new_plane_state->src_w >> 16;
	src_h = new_plane_state->src_h >> 16;
	crtc_x = new_plane_state->crtc_x;
	crtc_y = new_plane_state->crtc_y;
@@ -500,6 +531,16 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,

	/* Enable DMA */
	kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);

	/* Save initial display config */
	if (!init_disp_cfg->width ||
	    !init_disp_cfg->height ||
	    !init_disp_cfg->format) {
		init_disp_cfg->width = width;
		init_disp_cfg->height = height;
		init_disp_cfg->format = fb->format->format;
	}

	drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg,
		kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id)));

+6 −0
Original line number Diff line number Diff line
@@ -63,6 +63,12 @@ struct layer_status {
	u32 ctrl;
};

struct disp_cfg {
	unsigned int width;
	unsigned int height;
	unsigned int format;
};

struct kmb_plane *kmb_plane_init(struct drm_device *drm);
void kmb_plane_destroy(struct drm_plane *plane);
#endif /* __KMB_PLANE_H__ */