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

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.comSigned-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
parent 13047a09
......@@ -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;
......
......@@ -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)));
......
......@@ -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__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment